diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index 66915777de..a2f157be30 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs @@ -9,6 +9,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { public ModelExpression AspFor { get; set; } + public string Label { get; set; } + [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 6a0c161ae2..3f9cc6e523 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -1,11 +1,14 @@ -using System.Linq; +using System; +using System.Linq; using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @@ -13,34 +16,44 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form public class AbpInputTagHelperService : AbpTagHelperService { private readonly IHtmlGenerator _generator; + private readonly HtmlEncoder _encoder; + private readonly IStringLocalizer _localizer; - public AbpInputTagHelperService(IHtmlGenerator generator) + public AbpInputTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IStringLocalizer localizer) { _generator = generator; + _encoder = encoder; + _localizer = localizer; } public override void Process(TagHelperContext context, TagHelperOutput output) { - output.TagName = "input"; + output.TagName = "div"; + output.TagMode = TagMode.StartTagAndEndTag; + + var inputTag = GetInputTag(); + var inputHtml = RenderTagHelperOutput(inputTag, _encoder); + var isCheckbox = IsInputCheckbox(inputTag.Attributes); - ProcessAttributes(output); - } + var label = GetLabelAsHtml(inputTag, isCheckbox); - protected virtual void ProcessAttributes(TagHelperOutput output) - { - output.Attributes.RemoveAll("asp-for"); + var content = isCheckbox ? + inputHtml + Environment.NewLine + label : + label + Environment.NewLine + inputHtml; - var inputTagHelperOutput = GetAttributes(output); + output.Content.SetHtmlContent(content); - foreach (var tagHelperAttribute in inputTagHelperOutput.Attributes) - { - output.Attributes.Add(tagHelperAttribute); - } + SetDivAttributes(output, isCheckbox); + } + + protected virtual void SetDivAttributes(TagHelperOutput output, bool isCheckbox) + { + output.Attributes.RemoveAll("asp-for"); - output.Attributes.Add("class", "form-control"); + output.Attributes.Add("class", isCheckbox ? " form-check" : "form-group"); } - protected virtual TagHelperOutput GetAttributes(TagHelperOutput output) + protected virtual TagHelperOutput GetInputTag() { var inputTagHelper = new InputTagHelper(_generator) { @@ -48,7 +61,45 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form ViewContext = TagHelper.ViewContext }; - return GetInnerTagHelper(new TagHelperAttributeList(), inputTagHelper); + var inputTagHelperOutput = GetInnerTagHelper(new TagHelperAttributeList(), inputTagHelper, "input"); ; + + inputTagHelperOutput.Attributes.Add("class", + IsInputCheckbox(inputTagHelperOutput.Attributes) ? "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 label = GetLabelText(); + var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); + var idAttrAsString = ""; + + if (idAttr != null) + { + idAttrAsString = "for=\"" + idAttr.Value + "\""; + } + + var checkboxClass = isCheckbox ? "class=\"form-check-label\" " : ""; + + return ""; + } + + protected virtual string GetLabelText() + { + return string.IsNullOrEmpty(TagHelper.Label) ? + TagHelper.AspFor.Metadata.DisplayName : + TagHelper.Label; } } } \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs index a7285aa233..cf2786e726 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs @@ -10,6 +10,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { public ModelExpression AspFor { get; set; } + public string Label { get; set; } + public IEnumerable AspItems { get; set; } [HtmlAttributeNotBound] diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index b132d77e75..62ec7d819f 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -1,10 +1,14 @@ -using System.Text; +using System; +using System.Linq; +using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @@ -13,24 +17,38 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { private readonly IHtmlGenerator _generator; private readonly HtmlEncoder _encoder; + private readonly IStringLocalizer _localizer; - public AbpSelectTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder) + public AbpSelectTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IStringLocalizer localizer) { _generator = generator; _encoder = encoder; + _localizer = localizer; } public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; - output.Attributes.Add("class", "form-control"); + SetDivAttributes(output); output.TagMode = TagMode.StartTagAndEndTag; - output.Content.SetHtmlContent(GetInnerHtml(output)); - output.Attributes.Clear(); + var selectTag = GetSelectTag(); + + var seelctAsHtml = RenderTagHelperOutput(selectTag, _encoder); + var labelAsHtml = GetLabelAsHtml(selectTag); + var content = labelAsHtml + Environment.NewLine + seelctAsHtml; + + output.Content.SetHtmlContent(content); + } + + protected virtual void SetDivAttributes(TagHelperOutput output) + { + output.Attributes.RemoveAll("asp-for"); + output.Attributes.RemoveAll("asp-items"); + output.Attributes.Add("class", "form-group"); } - protected virtual string GetInnerHtml(TagHelperOutput output) + protected virtual TagHelperOutput GetSelectTag() { var selectTagHelper = new SelectTagHelper(_generator) { @@ -39,7 +57,39 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form ViewContext = TagHelper.ViewContext }; - return RenderTagHelper(output.Attributes, selectTagHelper, _encoder, "select", TagMode.StartTagAndEndTag); + var attributes = new TagHelperAttributeList { new TagHelperAttribute("class", "form-control") }; + var inputTagHelperOutput = GetInnerTagHelper(attributes, 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 ""; + } + + var label = GetLabelText(); + var idAttr = selectTag.Attributes.FirstOrDefault(a => a.Name == "id"); + var idAttrAsString = ""; + + if (idAttr != null) + { + idAttrAsString = "for=\"" + idAttr.Value + "\""; + } + + return ""; + } + + protected virtual string GetLabelText() + { + return string.IsNullOrEmpty(TagHelper.Label) ? + TagHelper.AspFor.Metadata.DisplayName : + TagHelper.Label; } } } \ No newline at end of file diff --git a/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Forms.cshtml b/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Forms.cshtml index 8df0e4440a..4db1d3782a 100644 --- a/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Forms.cshtml +++ b/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Forms.cshtml @@ -14,66 +14,97 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + +
       
         <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>
+            <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>
         
-
\ No newline at end of file + + +@*
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+            <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>
+            
+
+
*@ \ No newline at end of file