How to disable an HyperLink in ASP.NET MVC3 with Html Helpers without spoiling the View?

22,685

Solution 1

I i understood correctly, main problem is that you don't wish to create additional If -s. I would do custom helper in your place

public static MvcHtmlString ActionLink<TModel>(this HtmlHelper<TModel> helper, string linkText, string action, object routeValues, bool disable)
    {
        if (disable)
        {
            return helper.ActionLink(linkText, action, routeValues, new { disabled = "disabled" });
        }
        return helper.ActionLink(linkText, action, routeValues);
    }

and pass the last value, as you use to, but in parameter, without @if

    @Html.ActionLink("Presentation", "Download", topic.EnableTopicDownloadLink)

My code needs modifications to accept custom htmlattributes (topicId) and merge with disabled. For this, you could use HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); and merge disabled attribute with returned value in method body

Solution 2

i would suggest rendering actionlink and assigning some class conditionally. e.g

@Html.ActionLink("Video", "Play", new { topicId = topic.TopicId },new{@class = topic.EnableTopicWatchLink?"":"dis"} )n

then you can use some css to gray it out and remove the underline

<style type="text/css">   
 a.dis
    {
      color:gray;
      text-decoration:none;
    }
</style>

and to cancel the default behavior of link some js would work

 <script type = "text/javascript">
    $('a.dis').live('click',function(){
    return false; // cancels the default operation of click function
    });
    </script>

Solution 3

Because MVC is stateless, there is no concept of state management like webforms. In other words, you cannot simply "enable" or "disable" a link in the sense that you're asking. You seem to be doing it correctly, albeit a little more verbose than you need to. You do a post and your action methods make the decision to enable/disable the link before the view is rendered, then your view must check if it's allowed to show the link or not. You could then pass along a model property like this:

@(Model.TopicWatchLink ? Html.ActionLink("Video", "Play", new { topicId = topic.TopicId }) : "N/A")

That is basically what you're doing already, but placed in an inline IF to take up less space.

Another option you might consider is @Html.RenderAction("someAction"). This allows you to call an action method (and pass in parameters if you wish) from your view when it's being rendered. You could then put the logic that determines whether or not to show the view in the said action method and have the action return the link html. While you could put the HTML in a string, I recommend you define a partial view or use the TagBuilder class to build your link and return it. Ex:

public MvcHtmlString GenerateLink(bool enabled)
{
    if (enabled)
    {
        var tagBuilder = new TagBuilder("a");
        tagBuilder.MergAttribute("src", Url.Action("Video", "Play")); // Pseudo-code
        return tagBuilder.ToString(TagRenderMode.SelfClosing);
    }
    else
        return "N/A";
}

Then in your view:

@Html.RenderAction("GenerateLink", new { enabled = Model.TopicWatchLink }); // Pseudo-code

Some of that is pseudo-code (i.e. has not been tested and may not exactly match the real code) but you get the idea. You could also do this in an html helper.

See here for details on creating HTML helpers. If it were me I would use ActionLink in a custom helper and just accept a boolean that would determine what to render.

There are a number of different options available to you. Just remember that MVC is stateless and it's up to you to make those kinds of logic decisions as well as implement them. It might be easier in webforms to call linkButton.Disabled = true; but you have not idea what ASP.NET does to disable it. Basically you have no control over how the disabling happens and you can remain ignorant to the underlying HTML/CSS. MVC is about working intimately with this process. It might be more verbose that setting disabled to true, but in my opinion it is worth doing to see through the abstraction.

Share:
22,685

Related videos on Youtube

CiccioMiami
Author by

CiccioMiami

Updated on June 17, 2020

Comments

  • CiccioMiami
    CiccioMiami almost 4 years

    I am developing an ASP.NET MVC3 application with Razor and C#. I wanted to know if there is any way to "disable" an hyperlink rendered with the Html.ActionLink helper without spoiling my View with if constructs. As for disable I mean the link becomes not clickable, greyed out and without the underline.

    To make things clear I hereby attach the as-is code I currently use to make the trick. Instead of disabling the hyperlink I just display N/A as plain text.

    The part of the View:

     <td>@if(topic.EnableTopicDownloadLink)
        {
            @Html.ActionLink("Presentation", "Download", new { topicId = topic.TopicId })
        }
        else
        {
             @Html.Raw("N/A");
        }           
    </td>
    
    <td>@if (topic.EnableTopicWatchLink)
        {
            @Html.ActionLink("Video", "Play", new { topicId = topic.TopicId })
        }
        else
        {
            @Html.Raw("N/A");
        }     
    </td>
    

    And the ViewModel passed to the View

    public class TopicDownloadViewModel
        {
            public int TopicId { get; set; }
            public string TopicName { get; set; }
            public string TopicPresenter { get; set; }
            public string TopicStartTime { get; set; }
            public string TopicEndTime { get; set; }
            public bool EnableTopicWatchLink { get; set; }
            public bool EnableTopicDownloadLink { get; set; }
    
            public TopicDownloadViewModel(WebinarTopic webinarTopic)
            {
                TopicId = webinarTopic.TopicId;
                TopicName = webinarTopic.TopicName;
                TopicPresenter = webinarTopic.TopicPresenter;
                TopicStartTime = String.Format("{0:t}", webinarTopic.TopicStartTime);
                TopicEndTime = String.Format("{0:t}", webinarTopic.TopicEndTime);
                EnableTopicWatchLink = (webinarTopic.TopicVideoWatchLink != null) ? true : false;
                EnableTopicDownloadLink = (webinarTopic.TopicSlidesDownloadLink != null) ? true : false;
            }
        }
    

    I know there is a disabled HTML attribute for <a> but the only way to enable the link is to omit the attribute and I have no clue how to do it without using jQuery. My intension is not to use jquery if feasible.

    Thanks

    Francesco

  • Chev
    Chev almost 13 years
    +1, this is the route I would go as well if it were me. Instead of repeating the same IF condition over and over I would encapsulate that simple logic in a custom helper.
  • archil
    archil almost 13 years
    yep, html standart does not contain disabled attribute for the anchor tag. But main point in my answer was where the place the custom reusable view logic. I showed that the best place for it is inside custom helper. Code can be simply modified to generate text instead of anchor when disabled
  • NoWar
    NoWar over 9 years