I use asp core 2.0 MVC and often use code like this in a form:
<form asp-controller="Foo" asp-action="Bar">
<div class="form-group">
<label asp-for="Age"></label>
<input asp-for="Age" class="form-control"/>
<span asp-validation-for="Age" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control"/>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</form>
Is there a way to combine the label, input and span tag in a TagHelper class to just write something like this:
<div class="form-group">
<foo for="Age">
</div>
which will produce the following:
<label asp-for="Age"></label>
<input asp-for="Age" class="form-control"/>
<span asp-validation-for="Age" class="text-danger"></span>
to avoid writing this 3 common tags for my properties over and over again?
Thank you in advance.
EDIT:
Hey Isma, thank you for your answer. Your code generates plain
<label asp-for="Age"></label>
<input asp-for="Age" class="form-control"/>
<span asp-validation-for="Age" class="text-danger"></span>
html.
But I would like the 'Processed' version like
<input asp-for="Age"/>
is
<input type="number" data-val="true" data-val-range="The field Age must be between 0 and 100." data-val-range-max="100" data-val-range-min="0" data-val-required="The Age field is required." id="Age" name="Age" value="" />
in html
is there a way to achieve this?
This may work for you or at least get you in the right direction, I used a custom TagHelper that generates the other elements using their TagHelper implementation and appends all the outputs (may be there is a better / cleaner way of doing this, by the way).
[HtmlTargetElement("myfield")]
public class MyFieldTagHelper : TagHelper
{
private IHtmlGenerator _htmlGenerator;
public MyFieldTagHelper(IHtmlGenerator htmlGenerator)
{
_htmlGenerator = htmlGenerator;
}
public string LabelContent { get; set; }
public string ValidationContent { get; set; }
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; }
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var labelContext = CrateTagHelperContext();
var labelOutput = CrateTagHelperOutput("label");
labelOutput.Content.Append(LabelContent);
if (For != null)
{
labelOutput.Attributes.Add("for", For.Name);
}
var label = new LabelTagHelper(_htmlGenerator)
{
ViewContext = ViewContext
};
label.Process(labelContext, labelOutput);
var inputContext = CrateTagHelperContext();
var inputOutput = CrateTagHelperOutput("input");
inputOutput.Attributes.Add("class", "form-control");
var input = new InputTagHelper(_htmlGenerator)
{
For = For,
ViewContext = ViewContext
};
input.Process(inputContext, inputOutput);
var validationContext = CrateTagHelperContext();
var validationOutput = CrateTagHelperOutput("span");
validationOutput.Content.Append(ValidationContent);
validationOutput.Attributes.Add("class", "text-danger");
var validation = new ValidationMessageTagHelper(_htmlGenerator)
{
For = For,
ViewContext = ViewContext
};
validation.Process(validationContext, validationOutput);
output.TagName = "";
output.Content.AppendHtml(labelOutput);
output.Content.AppendHtml(inputOutput);
output.Content.AppendHtml(validationOutput);
}
private static TagHelperContext CrateTagHelperContext()
{
return new TagHelperContext(
new TagHelperAttributeList(),
new Dictionary<object, object>(),
Guid.NewGuid().ToString("N"));
}
private static TagHelperOutput CrateTagHelperOutput(string tagName)
{
return new TagHelperOutput(
tagName,
new TagHelperAttributeList(),
(a,b) =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent(string.Empty);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
}
}
Now in your view you should be able to do this:
<myfield label-content="This is a label" validation-content="Validation content" asp-for="Age"></myfield>
And it will generate the whole block for you.
Remember to register the assembly where you have your tag helpers, even if you have them in your Web application, you can do that by editing the file Views/_ViewImports.cshtml and adding the following line:
@addTagHelper *, YourAssemblyName
More info: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro