Reputation: 16743
I have a tag helper along the lines of the following:
[HtmlTargetElement("foo", Attributes = "bar")]
public class FooTagHelper : TagHelper
[HtmlAttributeName("bar")]
public bool Bar { get; set; }
When I add the following to a view, the tag helper processes the target as expected:
<foo bar="true"></foo>
However, what I would like to do is make bar
optional e.g. <foo></foo>
If it has been left off, I would like it to default to false
Is this possible? This source code comment for the HtmlTargetElementAttribute.Attributes
property seems to indicate not:
// Summary:
A comma-separated System.String of attribute names the HTML element must contain
for the Microsoft.AspNet.Razor.TagHelpers.ITagHelper to run. * at the end of an attribute name acts as a prefix match.
Upvotes: 4
Views: 4574
Reputation: 1150
The only way I was able to get attributes to be optional is if I did not include them in the Attributes
section of HtmlTargetElement
.
so this [HtmlTargetElement("foo", Attributes = "bar")]
changes to [HtmlTargetElement("foo")]
then also remove the [HtmlAttributeName("bar")]
here:
[HtmlAttributeName("bar")]
public bool Bar { get; set; }
so completed changes look like:
[HtmlTargetElement("foo")]
public class FooTagHelper : TagHelper
{
public bool Bar { get; set; }
public string FooBar { get; set; }
}
also make sure any properties you reference in your tag are kebab-case, example:
<foo bar="true" foo-bar="make sure to use kebab-case!"></foo>
Upvotes: 0
Reputation: 559
If you wan't to check if the optional attribute is explicitly specified in the Html, you can check context.AllAttributes
, you won't find it in output.Attributes
as specified in the previous post.
I noticed that my TagHelper wasn't rendered if I left away the (optional) attribute OnlyUrlOfMenuItem
in the Html. I just had to remove the attribute OnlyUrlOfMenuItem
from the list of required attributes HtmlTargetElement()
as stated by Mat Hellums above. Since I don't want this attribute to appear in the final output, I didn't need to add the attribute with output.Attributes.Add()
as stated in the previous post.
Here is my code with the optional attribute OnlyUrlOfMenuItem
that has a default value of false
:
[HtmlTargetElement("a", Attributes = "MenuItem, LangCode")]
public class ATagHelper : TagHelper
{
readonly IFhpMenuProvider _fhpMenuProvider;
public ATagHelper(IFhpMenuProvider fhpMenuProvider)
{
_fhpMenuProvider = fhpMenuProvider;
OnlyUrlOfMenuItem = false;
}
[HtmlAttributeName("LangCode")]
public string LangCode { get; set; }
[HtmlAttributeName("MenuItem")]
public string MenuItemKey { get; set; }
[HtmlAttributeName("OnlyUrlOfMenuItem")]
public bool OnlyUrlOfMenuItem { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
MenuItem menuItem = _fhpMenuProvider.GetMenuItem(MenuItemKey, LangCode);
if (menuItem != null)
{
...
if (string.IsNullOrEmpty(menuItem.Tooltip) == false && OnlyUrlOfMenuItem == false)
{
output.Attributes.SetAttribute("title", menuItem.Tooltip);
}
if (string.IsNullOrEmpty(menuItem.Caption) == false && OnlyUrlOfMenuItem == false)
{
output.Content.SetContent(menuItem.Caption);
}
}
base.Process(context, output);
}
Upvotes: 1
Reputation: 382
You could remove "bar" from being a required attribute.
You can do that by overriding the Process method and checking whether the attribute exists. If it does not, add the Bar attribute using its name and value. You could explicitly set the value to false
but the property Bar is false by default anyway.
[HtmlTargetElement("foo")]
public class FooTagHelper : TagHelper
{
[HtmlAttributeName("bar")]
public bool Bar { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!output.Attributes.ContainsName(nameof(Bar)))
{
output.Attributes.Add(nameof(Bar), Bar);
}
}
}
Cheers!
If you have not yet done so, I would suggest taking a look at the documentation available here https://docs.asp.net/projects/mvc/en/latest/views/tag-helpers/index.html.
Upvotes: 7