mirror of https://github.com/abpframework/abp.git
committed by
GitHub
21 changed files with 834 additions and 25 deletions
@ -0,0 +1,22 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpDynamicFormTagHelper : AbpTagHelper<AbpDynamicFormTagHelper, AbpDynamicFormTagHelperService> |
||||
|
{ |
||||
|
[HtmlAttributeName("asp-model")] |
||||
|
public ModelExpression Model { get; set; } |
||||
|
|
||||
|
[HtmlAttributeNotBound] |
||||
|
[ViewContext] |
||||
|
public ViewContext ViewContext { get; set; } |
||||
|
|
||||
|
public AbpDynamicFormTagHelper(AbpDynamicFormTagHelperService tagHelperService) |
||||
|
: base(tagHelperService) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,184 @@ |
|||||
|
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; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicFormTagHelper> |
||||
|
{ |
||||
|
private readonly HtmlEncoder _htmlEncoder; |
||||
|
private readonly AbpInputTagHelper _abpInputTagHelper; |
||||
|
private readonly AbpSelectTagHelper _abpSelectTagHelper; |
||||
|
|
||||
|
public AbpDynamicFormTagHelperService(HtmlEncoder htmlEncoder, AbpInputTagHelper abpInputTagHelper, AbpSelectTagHelper abpSelectTagHelper) |
||||
|
{ |
||||
|
_htmlEncoder = htmlEncoder; |
||||
|
_abpInputTagHelper = abpInputTagHelper; |
||||
|
_abpSelectTagHelper = abpSelectTagHelper; |
||||
|
} |
||||
|
|
||||
|
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var list = InitilizeFormGroupContentsContext(context); |
||||
|
|
||||
|
await output.GetChildContentAsync(); |
||||
|
|
||||
|
ProcessFields(context, output); |
||||
|
|
||||
|
SetContent(output,list); |
||||
|
} |
||||
|
|
||||
|
protected virtual void SetContent(TagHelperOutput output, List<FormGroupContent> list) |
||||
|
{ |
||||
|
foreach (var itemConfig in list.OrderBy(o => o.Order)) |
||||
|
{ |
||||
|
output.PostContent.SetHtmlContent(output.PostContent.GetContent() + itemConfig.Html); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual void SetFormAttributes(TagHelperOutput output) |
||||
|
{ |
||||
|
output.TagName = "form"; |
||||
|
output.Attributes.Add("method", "post"); |
||||
|
output.Attributes.Add("action", "#"); |
||||
|
} |
||||
|
|
||||
|
protected virtual List<FormGroupContent> InitilizeFormGroupContentsContext(TagHelperContext context) |
||||
|
{ |
||||
|
var list = new List<FormGroupContent>(); |
||||
|
context.Items.Add(FormGroupContents, list); |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
protected virtual void ProcessFields(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var models = GetModels(context, output); |
||||
|
|
||||
|
foreach (var model in models) |
||||
|
{ |
||||
|
if (IsSelectGroup(context, model, out var selectItems)) |
||||
|
{ |
||||
|
ProcessSelectGroup(context, model, selectItems); |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
ProcessInputGroup(context, model); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual void ProcessSelectGroup(TagHelperContext context, ModelExpression model, IEnumerable<SelectListItem> selectItems) |
||||
|
{ |
||||
|
_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) |
||||
|
{ |
||||
|
_abpInputTagHelper.AspFor = model; |
||||
|
_abpInputTagHelper.Label = ""; |
||||
|
_abpInputTagHelper.ViewContext = TagHelper.ViewContext; |
||||
|
|
||||
|
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)) |
||||
|
{ |
||||
|
list.Add(ModelExplorerToModelExpressionConverter(model)); |
||||
|
|
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
if (IsListOfSelectItem(model.ModelType)) |
||||
|
{ |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
return model.Properties.Aggregate(list, ExploreModelsRecursively); |
||||
|
} |
||||
|
|
||||
|
protected virtual ModelExpression ModelExplorerToModelExpressionConverter(ModelExplorer explorer) |
||||
|
{ |
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
protected virtual bool IsCsharpClassOrPrimitive(Type type) |
||||
|
{ |
||||
|
return type.IsPrimitive || |
||||
|
type.IsValueType || |
||||
|
type == typeof(DateTime) || |
||||
|
type == typeof(ValueType) || |
||||
|
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.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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpInputTagHelper : AbpTagHelper<AbpInputTagHelper, AbpInputTagHelperService>, ITransientDependency |
||||
|
{ |
||||
|
public ModelExpression AspFor { get; set; } |
||||
|
|
||||
|
public string Label { get; set; } |
||||
|
|
||||
|
[HtmlAttributeNotBound] |
||||
|
[ViewContext] |
||||
|
public ViewContext ViewContext { get; set; } |
||||
|
|
||||
|
public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) |
||||
|
: base(tagHelperService) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,116 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using System.Text.Encodings.Web; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding; |
||||
|
using Microsoft.AspNetCore.Mvc.TagHelpers; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpInputTagHelperService : AbpTagHelperService<AbpInputTagHelper> |
||||
|
{ |
||||
|
private readonly IHtmlGenerator _generator; |
||||
|
private readonly HtmlEncoder _encoder; |
||||
|
private readonly IStringLocalizer<AbpUiResource> _localizer; |
||||
|
|
||||
|
public AbpInputTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IStringLocalizer<AbpUiResource> localizer) |
||||
|
{ |
||||
|
_generator = generator; |
||||
|
_encoder = encoder; |
||||
|
_localizer = localizer; |
||||
|
} |
||||
|
|
||||
|
public override void Process(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var html = GetFormInputGroupAsHtml(context, output); |
||||
|
|
||||
|
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer); |
||||
|
|
||||
|
AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, html, order); |
||||
|
|
||||
|
output.SuppressOutput(); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var inputTag = GetInputTag(context, out var isCheckbox); |
||||
|
var inputHtml = RenderTagHelperOutput(inputTag, _encoder); |
||||
|
var label = GetLabelAsHtml(inputTag, isCheckbox); |
||||
|
|
||||
|
var validation = isCheckbox ? "" : GetValidationAsHtml(context); |
||||
|
|
||||
|
return GetContent(label, inputHtml, validation, isCheckbox); |
||||
|
} |
||||
|
protected virtual string GetValidationAsHtml(TagHelperContext context) |
||||
|
{ |
||||
|
var validationMessageTagHelper = new ValidationMessageTagHelper(_generator) |
||||
|
{ |
||||
|
For = TagHelper.AspFor, |
||||
|
ViewContext = TagHelper.ViewContext |
||||
|
}; |
||||
|
|
||||
|
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } }; |
||||
|
|
||||
|
return RenderTagHelper(attributeList, context, validationMessageTagHelper, _encoder, "span", TagMode.StartTagAndEndTag, true); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetContent(string label, string inputHtml, string validation, bool isCheckbox) |
||||
|
{ |
||||
|
var innerContent = isCheckbox ? |
||||
|
inputHtml + Environment.NewLine + label : |
||||
|
label + Environment.NewLine + inputHtml; |
||||
|
|
||||
|
return "<div class=\"" + (isCheckbox ? "form-check" : "form-group") + "\">" + |
||||
|
Environment.NewLine + innerContent + Environment.NewLine + |
||||
|
Environment.NewLine + validation + Environment.NewLine + |
||||
|
"</div>"; |
||||
|
} |
||||
|
|
||||
|
protected virtual TagHelperOutput GetInputTag(TagHelperContext context, out bool isCheckbox) |
||||
|
{ |
||||
|
var inputTagHelper = new InputTagHelper(_generator) |
||||
|
{ |
||||
|
For = TagHelper.AspFor, |
||||
|
ViewContext = TagHelper.ViewContext |
||||
|
}; |
||||
|
|
||||
|
var inputTagHelperOutput = GetInnerTagHelper(new TagHelperAttributeList(), context, inputTagHelper, "input"); |
||||
|
isCheckbox = IsInputCheckbox(inputTagHelperOutput.Attributes); |
||||
|
|
||||
|
inputTagHelperOutput.Attributes.Add("class", isCheckbox ? "form-check-input" : "form-control"); |
||||
|
|
||||
|
return inputTagHelperOutput; |
||||
|
} |
||||
|
|
||||
|
protected virtual bool IsInputCheckbox(TagHelperAttributeList attributes) |
||||
|
{ |
||||
|
return attributes.Any(a => a.Value != null && a.Name == "type" && a.Value.ToString() == "checkbox"); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetLabelAsHtml(TagHelperOutput inputTag, bool isCheckbox) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(TagHelper.Label) && string.IsNullOrEmpty(TagHelper.AspFor.Metadata.DisplayName)) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
var checkboxClass = isCheckbox ? "class=\"form-check-label\" " : ""; |
||||
|
|
||||
|
return "<label " + checkboxClass + GetIdAttributeAsString(inputTag) + ">" |
||||
|
+ _localizer[GetLabelValue()] + |
||||
|
"</label>"; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetLabelValue() |
||||
|
{ |
||||
|
return string.IsNullOrEmpty(TagHelper.Label) ? |
||||
|
TagHelper.AspFor.Metadata.DisplayName : |
||||
|
TagHelper.Label; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpSelectTagHelper : AbpTagHelper<AbpSelectTagHelper, AbpSelectTagHelperService>, ITransientDependency |
||||
|
{ |
||||
|
public ModelExpression AspFor { get; set; } |
||||
|
|
||||
|
public string Label { get; set; } |
||||
|
|
||||
|
public IEnumerable<SelectListItem> AspItems { get; set; } |
||||
|
|
||||
|
[HtmlAttributeNotBound] |
||||
|
[ViewContext] |
||||
|
public ViewContext ViewContext { get; set; } |
||||
|
|
||||
|
public AbpSelectTagHelper(AbpSelectTagHelperService tagHelperService) |
||||
|
: base(tagHelperService) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Encodings.Web; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.AspNetCore.Mvc.TagHelpers; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper> |
||||
|
{ |
||||
|
private readonly IHtmlGenerator _generator; |
||||
|
private readonly HtmlEncoder _encoder; |
||||
|
private readonly IStringLocalizer<AbpUiResource> _localizer; |
||||
|
|
||||
|
public AbpSelectTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IStringLocalizer<AbpUiResource> localizer) |
||||
|
{ |
||||
|
_generator = generator; |
||||
|
_encoder = encoder; |
||||
|
_localizer = localizer; |
||||
|
} |
||||
|
|
||||
|
public override void Process(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var html = GetFormInputGroupAsHtml(context, output); |
||||
|
|
||||
|
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer); |
||||
|
|
||||
|
AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, html, order); |
||||
|
|
||||
|
output.SuppressOutput(); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
var selectTag = GetSelectTag(context); |
||||
|
var selectAsHtml = RenderTagHelperOutput(selectTag, _encoder); |
||||
|
var label = GetLabelAsHtml(selectTag); |
||||
|
|
||||
|
return GetContent(label, selectAsHtml); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetContent(string label, string inputHtml) |
||||
|
{ |
||||
|
var innerContent = label + Environment.NewLine + inputHtml; |
||||
|
|
||||
|
return "<div class=\"form-group\">" + Environment.NewLine + innerContent + Environment.NewLine + "</div>"; |
||||
|
} |
||||
|
|
||||
|
protected virtual TagHelperOutput GetSelectTag(TagHelperContext context) |
||||
|
{ |
||||
|
var selectTagHelper = new SelectTagHelper(_generator) |
||||
|
{ |
||||
|
For = TagHelper.AspFor, |
||||
|
Items = TagHelper.AspItems, |
||||
|
ViewContext = TagHelper.ViewContext |
||||
|
}; |
||||
|
|
||||
|
var inputTagHelperOutput = GetInnerTagHelper(new TagHelperAttributeList(), context,selectTagHelper, "select", TagMode.StartTagAndEndTag); ; |
||||
|
|
||||
|
inputTagHelperOutput.Attributes.Add("class", "form-control"); |
||||
|
|
||||
|
return inputTagHelperOutput; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetLabelAsHtml(TagHelperOutput selectTag) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(TagHelper.Label) && string.IsNullOrEmpty(TagHelper.AspFor.Metadata.DisplayName)) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
return "<label " + GetIdAttributeAsString(selectTag) + ">" + _localizer[GetLabelText()] + "</label>"; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetLabelText() |
||||
|
{ |
||||
|
return string.IsNullOrEmpty(TagHelper.Label) ? |
||||
|
TagHelper.AspFor.Metadata.DisplayName : |
||||
|
TagHelper.Label; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
[HtmlTargetElement(Attributes = "asp-validation-for")] |
||||
|
public class AbpValidationAttributeTagHelper : AbpTagHelper<AbpValidationAttributeTagHelper, AbpValidationAttributeTagHelperService>, ITransientDependency |
||||
|
{ |
||||
|
public AbpValidationAttributeTagHelper(AbpValidationAttributeTagHelperService tagHelperService) |
||||
|
: base(tagHelperService) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Encodings.Web; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.AspNetCore.Mvc.TagHelpers; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Microsoft.AspNetCore.Razor.TagHelpers; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class AbpValidationAttributeTagHelperService : AbpTagHelperService<AbpValidationAttributeTagHelper> |
||||
|
{ |
||||
|
public override void Process(TagHelperContext context, TagHelperOutput output) |
||||
|
{ |
||||
|
output.Attributes.Add("class","text-danger"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Property)] |
||||
|
public class DisplayOrder : Attribute |
||||
|
{ |
||||
|
public int Number { get; set; } |
||||
|
|
||||
|
public DisplayOrder(int number) |
||||
|
{ |
||||
|
Number = number; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public class FormGroupContent |
||||
|
{ |
||||
|
public string Html { get; set; } |
||||
|
|
||||
|
public int Order { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Property)] |
||||
|
public class SelectItems: Attribute |
||||
|
{ |
||||
|
public string ItemsListPropertyName { get; set; } |
||||
|
|
||||
|
public SelectType SelectType { get; set; } = SelectType.Dropdown; |
||||
|
|
||||
|
public IEnumerable<SelectListItem> GetItems(ModelExplorer explorer) |
||||
|
{ |
||||
|
var properties = explorer.Container.Properties.Where(p => p.Metadata.PropertyName.Equals(ItemsListPropertyName)).ToList(); |
||||
|
|
||||
|
return properties.Count > 0 |
||||
|
? properties.First().Model as IEnumerable<SelectListItem> |
||||
|
: null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
public enum SelectType |
||||
|
{ |
||||
|
Dropdown, |
||||
|
Radio |
||||
|
} |
||||
|
} |
||||
@ -1,23 +1,128 @@ |
|||||
@page |
@page |
||||
@model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.FormsModel |
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components |
||||
|
@model FormsModel |
||||
|
|
||||
@{ |
@{ |
||||
ViewData["Title"] = "Forms"; |
ViewData["Title"] = "Forms"; |
||||
} |
} |
||||
|
|
||||
<h2>Forms</h2> |
<h2>Forms</h2> |
||||
|
|
||||
<p>Based on <a href="http://getbootstrap.com/docs/4.1/components/forms/" target="_blank"> Bootstrap form</a>.</p> |
<p>Based on <a href="http://getbootstrap.com/docs/4.1/components/forms/" target="_blank"> Bootstrap form</a>.</p> |
||||
|
|
||||
<h4># Example</h4> |
<h4># Dynamic Form Example</h4> |
||||
|
|
||||
<div class="demo-with-code"> |
<div class="demo-with-code"> |
||||
<div class="demo-area"> |
<div class="demo-area"> |
||||
|
<abp-dynamic-form asp-model="@Model.Ahmet"> |
||||
|
|
||||
|
</abp-dynamic-form> |
||||
</div> |
</div> |
||||
<div class="code-area"> |
<div class="code-area"> |
||||
<pre> |
<pre> |
||||
|
<abp-dynamic-form asp-model="Model.Ahmet" > |
||||
|
</abp-dynamic-form> |
||||
</pre> |
</pre> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
|
|
||||
|
@*<h4># Input Group Example</h4> |
||||
|
|
||||
|
<div class="demo-with-code"> |
||||
|
<div class="demo-area"> |
||||
|
<form method="post" action="#"> |
||||
|
<abp-input asp-for="@Model.Name" /> |
||||
|
<abp-input asp-for="@Model.Password" label="Password" /> |
||||
|
<abp-input asp-for="@Model.IsActive" /> |
||||
|
<abp-input asp-for="@Model.PhoneNumber" /> |
||||
|
<abp-input asp-for="@Model.EmailAddress" /> |
||||
|
<abp-input asp-for="@Model.Count" /> |
||||
|
<abp-input asp-for="@Model.Day" /> |
||||
|
<abp-select asp-for="@Model.Country" asp-items="@Model.Countries" label="Country"></abp-select> |
||||
|
<abp-select asp-for="@Model.City" asp-items="@Html.GetEnumSelectList(typeof(Cities))"></abp-select> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div class="code-area"> |
||||
|
<pre> |
||||
|
<form method="post" action="#"> |
||||
|
<abp-input asp-for="Model.Name"/> |
||||
|
<abp-input asp-for="Model.Password" label="Password"/> |
||||
|
<abp-input asp-for="Model.IsActive" /> |
||||
|
<abp-input asp-for="Model.PhoneNumber" /> |
||||
|
<abp-input asp-for="Model.EmailAddress" /> |
||||
|
<abp-input asp-for="Model.Count" /> |
||||
|
<abp-input asp-for="Model.Day" /> |
||||
|
<abp-select asp-for="Model.Country" asp-items="Model.Countries" label="Country"></abp-select> |
||||
|
<abp-select asp-for="Model.City" asp-items="Html.GetEnumSelectList(typeof(Cities))"></abp-select> |
||||
|
</form> |
||||
|
</pre> |
||||
|
</div> |
||||
|
</div>*@ |
||||
|
|
||||
|
@*<div class="demo-with-code"> |
||||
|
<div class="demo-area"> |
||||
|
<form method="post" action="#"> |
||||
|
<abp-form-group> |
||||
|
<abp-select asp-for="@Model.Country" asp-items="@Model.Countries"></abp-select> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-select asp-for="@Model.City" asp-items="@Html.GetEnumSelectList(typeof(Cities))"></abp-select> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Name" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Password" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.PhoneNumber" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.EmailAddress" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Count" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Day" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.IsActive" /> |
||||
|
</abp-form-group> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div class="code-area"> |
||||
|
<pre> |
||||
|
<form method="post" action="#"> |
||||
|
<abp-form-group> |
||||
|
<abp-select asp-for="@Model.Country" asp-items="@Model.Countries"></abp-select> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-select asp-for="@Model.City" asp-items="@Html.GetEnumSelectList(typeof(Cities))"></abp-select> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Name" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Password" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.PhoneNumber" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.EmailAddress" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Count" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.Day" /> |
||||
|
</abp-form-group> |
||||
|
<abp-form-group> |
||||
|
<abp-input asp-for="@Model.IsActive" /> |
||||
|
</abp-form-group> |
||||
|
</form> |
||||
|
</pre> |
||||
|
</div> |
||||
|
</div>*@ |
||||
@ -1,12 +1,83 @@ |
|||||
using Microsoft.AspNetCore.Mvc.RazorPages; |
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components |
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components |
||||
{ |
{ |
||||
public class FormsModel : PageModel |
public class FormsModel : PageModel |
||||
{ |
{ |
||||
|
public PersonViewModel Ahmet { get; set; } = new PersonViewModel(); |
||||
|
|
||||
public void OnGet() |
public void OnGet() |
||||
{ |
{ |
||||
|
Ahmet = new PersonViewModel |
||||
|
{ |
||||
|
Name = "ahmet", |
||||
|
Age = 65, |
||||
|
Phone = new Phone {Number = "326346231",Name = "MyPhone"} |
||||
|
}; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
public enum Cities |
||||
|
{ |
||||
|
Istanbul, |
||||
|
NewJersey, |
||||
|
Moscow |
||||
|
} |
||||
|
|
||||
|
public class PersonViewModel |
||||
|
{ |
||||
|
[Required] |
||||
|
[DisplayName("Name")] |
||||
|
public string Name { get; set; } = "MyName"; |
||||
|
|
||||
|
[Required] |
||||
|
[DisplayOrder(61)] |
||||
|
[DisplayName("Age")] |
||||
|
[Range(1, 100)] |
||||
|
public int Age { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DisplayName("City")] |
||||
|
public Cities City { get; set; } |
||||
|
|
||||
|
public Phone Phone { get; set; } |
||||
|
|
||||
|
[DataType(DataType.Date)] |
||||
|
[DisplayName("Day")] |
||||
|
public DateTime Day { get; set; } |
||||
|
|
||||
|
[DisplayOrder(51)] |
||||
|
[DisplayName("Is Active")] |
||||
|
public bool IsActive { get; set; } |
||||
|
|
||||
|
[DisplayName("Country")] |
||||
|
[SelectItems(ItemsListPropertyName = nameof(Countries))] |
||||
|
public string Country { get; set; } |
||||
|
|
||||
|
public List<SelectListItem> Countries { get; set; } = new List<SelectListItem> |
||||
|
{ |
||||
|
new SelectListItem { Value = "MX", Text = "Mexico" }, |
||||
|
new SelectListItem { Value = "CA", Text = "Canada" }, |
||||
|
new SelectListItem { Value = "US", Text = "USA" }, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public class Phone |
||||
|
{ |
||||
|
[Required] |
||||
|
[DisplayName("Number")] |
||||
|
public string Number { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DisplayOrder(71)] |
||||
|
[DisplayName("PhoneName")] |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
} |
} |
||||
Loading…
Reference in new issue