I have a simple menu in an ASP.NET MVC application allows a user to take one of several actions after first selecting a resource to work with from a drop down list / select box or textbox. In the case where the user hasn’t yet selected anything (or entered any text), I want the links to be disabled, as I’d rather let the user know the issue on the current dashboard page than have them go to a page without a required parameter and then hit them with an error message about the missing parameter. Instead, I’d like to, in the case of the empty textbox, give the textbox focus and flash some color there so the user (usually me) knows they need to enter something there before proceeding.
You can’t just .disable() a hyperlink or anchor tag using jQuery, nor can you .enable() it. There’s also a bit of magic involved in being able to take the contents of a textbox or select list and stick them into the URL in a link, which I’ll also show here. For my menu, it’s organized inside of an unordered list (<ul>) with individual list items (<li>) and anchors (<a>). It’s pretty straightforward to select and work on each such link using a jQuery selector.
Here’s the HTML for one of the two menus I’m working with, the one that requires a textbox. The other one is set up identically except it has a drop down list.
Getting the Value from the Textbox or DropDownList
The first thing I need in either menu is the value the user has provided in the <input type=text> or <select> form field. Here are the two ways to do this – jQuery 101 stuff:
Appending a Value to a Link in an Anchor
Enabling and Disabling Links using jQuery
The last step is to make sure that the links don’t work until the user has entered a value into the textbox (for the dropdownlist, it will always have some valid resource selected, so I don’t need to do this). The way you disable clicking on an anchor tag from navigating to the corresponding href URL is by binding the click() event and calling e.preventDefault(). This will prevent the default behavior of the click, namely the navigation to the URL. In my case, I’m doing this whenever the textbox has zero length – I could do more advanced validation but this is sufficient for this example – and when this occurs I’m also highlighting the textbox in red and giving it focus.
Once you’ve added a .click() event handler, you can’t simply add another one to undo the effect, as this will cause both to happen. So, you could wire up the .click() handler to call a named function, and do your validation checking in that function, or you can unbind the .click() handler when it’s not needed, which is the approach I’m showing here. The full function for adjusting the links in the email-based menu is shown below, which includes the code required to modify the URLs similarly to what was shown above.
Wiring Things Up
Once you have these things set up, all that remains is to wire them up when the page loads. In this case, we want the updating of the links to occur any time the corresponding UI element changes. I’m also setting up the textbox to autocomplete based on emails in the system already. In addition to firing when the UI element changes, I need the functions to each run one time when the page loads, so that the URLs are set accordingly and the links are disabled if the textbox is empty. Here’s the on-page-load function:
I’m far from being a jQuery expert, but I was able to get all of this working very quickly with some help from jQueryUI.com and StackOverflow.com, which has a ton of jQuery questions and answers. I’m not currently using an MVVM style of client-side programming, although I expect to learn to do so in the very near future using frameworks like Knockout and KendoUI, which for this code wouldn’t make a huge difference, but might clean it up some by letting me bind things to a model, rather than to the selected element of some UI element. This would clean up the menu link URL logic significantly, as I could just bind the links to a model with a property for the URL that was dynamically created, for instance. This is left as an exercise for the reader, or perhaps a follow-up article in the future.