|
|
|
@ -1,6 +1,7 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Reflection; |
|
|
|
using System.Text.Encodings.Web; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.AspNetCore.Mvc.Rendering; |
|
|
|
@ -13,11 +14,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
{ |
|
|
|
private readonly HtmlEncoder _htmlEncoder; |
|
|
|
private readonly AbpInputTagHelper _abpInputTagHelper; |
|
|
|
private readonly AbpSelectTagHelper _abpSelectTagHelper; |
|
|
|
|
|
|
|
public AbpDynamicFormTagHelperService(HtmlEncoder htmlEncoder, AbpInputTagHelper abpInputTagHelper) |
|
|
|
public AbpDynamicFormTagHelperService(HtmlEncoder htmlEncoder, AbpInputTagHelper abpInputTagHelper, AbpSelectTagHelper abpSelectTagHelper) |
|
|
|
{ |
|
|
|
_htmlEncoder = htmlEncoder; |
|
|
|
_abpInputTagHelper = abpInputTagHelper; |
|
|
|
_abpSelectTagHelper = abpSelectTagHelper; |
|
|
|
} |
|
|
|
|
|
|
|
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) |
|
|
|
@ -45,13 +48,24 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
|
|
|
|
foreach (var model in models) |
|
|
|
{ |
|
|
|
if (IsSelectGroup(context, model, out var selectItems)) |
|
|
|
{ |
|
|
|
ProcessSelectGroup(context, model, selectItems); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
ProcessInputGroup(context, model); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual List<ModelExpression> GetModels(TagHelperContext context, TagHelperOutput output) |
|
|
|
protected virtual void ProcessSelectGroup(TagHelperContext context, ModelExpression model, IEnumerable<SelectListItem> selectItems) |
|
|
|
{ |
|
|
|
return ExploreModelsRecursively(new List<ModelExpression>(), TagHelper.Model.ModelExplorer); |
|
|
|
_abpSelectTagHelper.AspFor = model; |
|
|
|
_abpSelectTagHelper.AspItems = selectItems; |
|
|
|
_abpSelectTagHelper.Label = ""; |
|
|
|
_abpSelectTagHelper.ViewContext = TagHelper.ViewContext; |
|
|
|
|
|
|
|
RenderTagHelper(new TagHelperAttributeList(), context, _abpSelectTagHelper, _htmlEncoder, "div", TagMode.StartTagAndEndTag); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void ProcessInputGroup(TagHelperContext context, ModelExpression model) |
|
|
|
@ -63,6 +77,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
RenderTagHelper(new TagHelperAttributeList(), context, _abpInputTagHelper, _htmlEncoder, "div", TagMode.StartTagAndEndTag); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual List<ModelExpression> GetModels(TagHelperContext context, TagHelperOutput output) |
|
|
|
{ |
|
|
|
return TagHelper.Model.ModelExplorer.Properties.Aggregate(new List<ModelExpression>(), ExploreModelsRecursively); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual List<ModelExpression> ExploreModelsRecursively(List<ModelExpression> list, ModelExplorer model) |
|
|
|
{ |
|
|
|
if (IsCsharpClassOrPrimitive(model.ModelType)) |
|
|
|
@ -71,6 +90,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
return list; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsListOfSelectItem(model.ModelType)) |
|
|
|
{ |
|
|
|
return list; |
|
|
|
} |
|
|
|
|
|
|
|
return model.Properties.Aggregate(list, ExploreModelsRecursively); |
|
|
|
} |
|
|
|
|
|
|
|
@ -78,13 +102,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
{ |
|
|
|
var temp = explorer; |
|
|
|
var propertyName = explorer.Metadata.PropertyName; |
|
|
|
|
|
|
|
|
|
|
|
while (temp?.Container?.Metadata?.PropertyName != null) |
|
|
|
{ |
|
|
|
temp = temp.Container; |
|
|
|
propertyName = temp.Metadata.PropertyName + "." + propertyName; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new ModelExpression(propertyName, explorer); |
|
|
|
} |
|
|
|
|
|
|
|
@ -94,17 +118,52 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
|
|
|
type.IsValueType || |
|
|
|
type == typeof(DateTime) || |
|
|
|
type == typeof(ValueType) || |
|
|
|
type == typeof(string) || |
|
|
|
type == typeof(decimal) || |
|
|
|
type == typeof(double) || |
|
|
|
type == typeof(String) || |
|
|
|
type == typeof(Decimal) || |
|
|
|
type == typeof(Double) || |
|
|
|
type == typeof(Guid) || |
|
|
|
type == typeof(Char) || |
|
|
|
type == typeof(Byte) || |
|
|
|
type == typeof(Boolean) || |
|
|
|
type == typeof(TimeSpan) || |
|
|
|
type == typeof(DateTimeOffset) || |
|
|
|
type == typeof(Int16) || |
|
|
|
type == typeof(Int32) || |
|
|
|
type == typeof(Int64) || |
|
|
|
type == typeof(ushort) || |
|
|
|
type == typeof(uint) || |
|
|
|
type == typeof(ulong) || |
|
|
|
type == typeof(float) || |
|
|
|
type == typeof(short) || |
|
|
|
type == typeof(int) || |
|
|
|
type == typeof(long) || |
|
|
|
type.IsEnum; |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual bool IsListOfSelectItem(Type type) |
|
|
|
{ |
|
|
|
return type == typeof(List<SelectListItem>) || type == typeof(IEnumerable<SelectListItem>); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model, out IEnumerable<SelectListItem> selectItems) |
|
|
|
{ |
|
|
|
return IsEnum(model.ModelExplorer, out selectItems) || AreSelectItemsProvided(model.ModelExplorer, out selectItems); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual bool IsEnum(ModelExplorer explorer, out IEnumerable<SelectListItem> selectItems) |
|
|
|
{ |
|
|
|
selectItems = explorer.Metadata.IsEnum ? GetSelectItemsFromEnum(explorer.ModelType) : null; |
|
|
|
return explorer.Metadata.IsEnum; |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual IEnumerable<SelectListItem> GetSelectItemsFromEnum(Type enumType) |
|
|
|
{ |
|
|
|
return enumType.GetTypeInfo().GetMembers(BindingFlags.Public | BindingFlags.Static) |
|
|
|
.Select((t, i) => new SelectListItem { Value = i.ToString(), Text = t.Name }).ToList(); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual bool AreSelectItemsProvided(ModelExplorer explorer, out IEnumerable<SelectListItem> selectItems) |
|
|
|
{ |
|
|
|
selectItems = GetAttribute<SelectItems>(explorer)?.GetItems(explorer); |
|
|
|
|
|
|
|
return selectItems != null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |