A lot of times we need a way to toggle the visibility of an element based on some server-side values. The most common example is if someone is logged in, show them more options than someone who is not logged in.
Option without Tag Helpers
This solution always felt a little dirty to me
What I’d like to do is to add an attribute off of div to toggle visibility. So instead I’d like something that looks like this:
So let’s create a custom Tag Helper to do this
- Create a TagHelpers folder in the root of your MVC project
- Create a new class called VisibilityTagHelper
- Copy and paste the super simple code below
- Go to /Views/_ViewImports.cshtml and add a line for all the TagHelpers in your project by doing @addTagHelper *, . Example below:
- Build your project *this is important or you won’t get intellisense*
- Start using it such as the example shown below (same as above)
- That’s it!
Or view the GitHub Commit that makes this happen
I also have a repo, where the first two commits are just the initial commit with a File => New Project. This 3rd commit outlines all the changes needed to make to get this to work if you’d rather learn via a Commit.
Breaking Down The Code
The code for the Visibility Tag Helper is pretty straight forward, but here’s a breakdown of it:
- HtmlTargetElement
- You first decorate your class with the HtmlTargetElement attribute to tell it that you’re targeting div’s.
[HtmlTargetElement("div")]
- You can target more than just divs by adding more attributes.
[HtmlTargetElement("div")] [HtmlTargetElement("a")]
- You could add the is-visible attribute to ALL elements by using *. This could be quite handy
[HtmlTargetElement("*")]
- UPDATE: 10/4/2018 – Per Andrew’s comment below, you can have this target all elements like above, but skip going through this TagHelper rendering by saying only run it if they have the
is-visible
attribute. This should save some perf as well as not give you purple tags in Visual Studio on all of your HTML elements. -
[HtmlTargetElement("*"
, Attributes = "is-visible"
)]
- You first decorate your class with the HtmlTargetElement attribute to tell it that you’re targeting div’s.
- Inherit from TagHelper.
- Naming the TagHelper doesn’t matter, as we are choosing the HtmlTargetElement. If we were making our own tag, then the tag would be based off of the name.
public class VisibilityTagHelper : TagHelper
- Naming the TagHelper doesn’t matter, as we are choosing the HtmlTargetElement. If we were making our own tag, then the tag would be based off of the name.
- Add a property to store the visibility of the tag.
- We need to default it to true, otherwise none of the HTML tags specified in the HtmlTargetElement will be visible, because booleans default to false. THAT IS REALLY IMPORTANT. The name will be kebab-cased which means each capital letter will be split by a dash. Example IsVisible becomes is-visible when using the tag.
public bool IsVisible { get; set; } = true;
- We need to default it to true, otherwise none of the HTML tags specified in the HtmlTargetElement will be visible, because booleans default to false. THAT IS REALLY IMPORTANT. The name will be kebab-cased which means each capital letter will be split by a dash. Example IsVisible becomes is-visible when using the tag.
- Override the Process method
- If the tag is set to not IsVisible, then we need to supress the output which will not render the tag at all. (Thanks to Damian Edwards for the tip about SuppressOutput())
public override void Process(TagHelperContext context, TagHelperOutput output) { if (!IsVisible) output.SuppressOutput(); base.Process(context, output); }
- If the tag is set to not IsVisible, then we need to supress the output which will not render the tag at all. (Thanks to Damian Edwards for the tip about SuppressOutput())
- That’s about it! Super simple.
Update 1/3/2017: As mentioned above – thanks to Damian Edwards for informing me of the output.SuppressOutput() method. That made things simpler.