Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Custom TagHelper for checkbox does not work #5968

Closed
gushwell opened this issue Mar 15, 2017 · 12 comments
Closed

Custom TagHelper for checkbox does not work #5968

gushwell opened this issue Mar 15, 2017 · 12 comments
Assignees

Comments

@gushwell
Copy link

I wrote a custom TagHelper class.
In this Process method, a new value is added to the class-attribute of checkbox, but no value is added.

In line number 197 of InputTagHelper.cs, the return value of GenerateCheckBox () has not been assigned, is it related to this problem?

@danroth27
Copy link
Member

Could you please share with us your TagHelper code so we can take a look?

@gushwell
Copy link
Author

gushwell commented Mar 16, 2017

It is my simplified code.
If there is no if-statement, I think that "myclass" is attached to all input tags, but it is not attached to only checkbox.

[HtmlTargetElement("input", Attributes = ForAttributeName)]
public class CheckedTagHelper : TagHelper {
    private const string ForAttributeName = "asp-for";

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression For { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output) {
        if (For.Metadata.ModelType == typeof(bool)) {
            var tb = new TagBuilder("input");
            tb.AddCssClass("myclass");
            output.MergeAttributes(tb);
        }
    }
}

@Eilon
Copy link
Member

Eilon commented Mar 16, 2017

@gushwell thanks for posting the code.

This attribute specifies that you want the tag helper to apply to all <input> tags that have an asp-for attribute on them:

[HtmlTargetElement("input", Attributes = ForAttributeName)]

You'd need to specify additional restrictions on that attribute to have it apply only when the <input> element's attributes include type="checkbox". You can check out the documentation for that attribute here: https://github.com/aspnet/Razor/blob/dev/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/HtmlTargetElementAttribute.cs#L48-L52 (or just see it in VS, of course)

Is that what you're trying to do?

If so, change it to something like this:

[HtmlTargetElement("input", Attributes = ForAttributeName + ",[type=checkbox]")]

@gushwell
Copy link
Author

gushwell commented Mar 16, 2017

@Eilon Thank you for your reply.

I tried changing the attribute as follows, but it did not work as intended.

[HtmlTargetElement ("input", Attributes = ForAttributeName + ", [type = checkbox]")]]

Also, changing it as follows (this was what I wanted to do), but it did not work as intended.

[HtmlTargetElement ("input", Attributes = "[type = checkbox]")]]

In this case, the Process method is certainly called.

I am using Microsoft.ASPNetCore.Mvc.TagHelpers (1.1.2).

@Eilon
Copy link
Member

Eilon commented Mar 16, 2017

@NTaylorMullen did I mess up the tag helper selector syntax? Any thoughts on this?

@Eilon
Copy link
Member

Eilon commented Mar 16, 2017

@gushwell maybe try removing all the extra spaces in your attribute?

So instead of:

[HtmlTargetElement ("input", Attributes = ForAttributeName + ", [type = checkbox]")]]

Try:

[HtmlTargetElement ("input", Attributes = ForAttributeName + ",[type=checkbox]")]]

?

@gushwell
Copy link
Author

gushwell commented Mar 17, 2017

@Eilon I changed the attribute and tried it.
But the result is incorrect

pattern-1

input

[HtmlTargetElement ("input", Attributes = ForAttributeName + ",[type=checkbox]")]
...
    public override void Process(TagHelperContext context, TagHelperOutput output) {
        var tb = new TagBuilder("input");
        tb.AddCssClass("myclass");
        output.MergeAttributes(tb);
    }

<input asp-for="BoolVal" class="my-control" type="checkbox" />
<input asp-for="StringVal" class="my-control" />

output

<input checked="checked" class="my-control" data-val="true" data-val-required="The BoolVal field is required." id="BoolVal" name="BoolVal" type="checkbox" value="true" />
<input class="my-control" type="text" id="StringVal" name="StringVal" value="example" />

pattern-2

input

[HtmlTargetElement("input")]
...
    public override void Process(TagHelperContext context, TagHelperOutput output) {
        var tb = new TagBuilder("input");
        tb.AddCssClass("myclass");
        output.MergeAttributes(tb);
    }

<input asp-for="BoolVal" class="my-control" type="checkbox" />
<input asp-for="StringVal" class="my-control" />

output

<input checked="checked" class="my-control" data-val="true" data-val-required="The BoolVal field is required." id="BoolVal" name="BoolVal" type="checkbox" value="true" />
<input class="my-control myclass" type="text" id="StringVal" name="StringVal" value="example" />

Question.
In pattern-2, "myclass" is added to the second input tag.
Why is not "myclass" added to the first (checkbox) tag?

@Eilon Eilon assigned Eilon and NTaylorMullen and unassigned Eilon Mar 17, 2017
@Eilon
Copy link
Member

Eilon commented Mar 17, 2017

@NTaylorMullen can you take a look?

@NTaylorMullen
Copy link
Contributor

@gushwell so the reason why your pattern-2 works and the first one does not is for multiple reasons.

  1. Your first pattern only applies to the first input tag (since it has type="checked") so it never has an opportunity to add the class to the second input tag.
  2. Your InputTagHelper runs after our InputTagHelper. Our InputTagHelper has already nuked the TagHelperOutput's tag name and shoved the checkbox tag into the inner content. Therefore, any attributes added don't make their way onto that tag. This is something we should look into changing so people can mutate our checkboxes. If you fix this by making your TagHelper run before the MVC TagHelper you run into this issue.
  3. Your pattern 2 runs on both of the input tags, does nothing for the first; and mutates the second as expected.

Hopefully these reasoning's shed some light on what you're seeing! You can work around the issue mentioned above by manually merging your class attribute instead of relying on the MergeAttributes extension method.

@Eilon
Copy link
Member

Eilon commented Mar 17, 2017

@NTaylorMullen can you file a new bug about clearing up how the checkbox tag helper works per our discussion?

@Eilon Eilon closed this as completed Mar 17, 2017
@NTaylorMullen
Copy link
Contributor

#5983

@MaqSaid
Copy link

MaqSaid commented Jun 28, 2018

Do we have working CheckboxTagHelper and final link of working code (with example would be great!)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants