ASP.Net Developers, it is time to change your attitude towards JavaScript. I know you hate it. I used to hate it too. But I’ve come to terms with JavaScript and now actually quite like it! It isn’t my favorite language but I’ve been working hard to understand this important client side technology.

Please don’t be offended by this post. I know I have lumped all ASP.Net developers into one category here. I know many of you are in the same place as I am, moving quickly towards understanding Javascript. I am, however, speaking to a large group of .Net web developers who have not yet started their journey. You know who you are.

I’m a C# MVP and, prior to this past summer, I spent 3 years doing Silverlight development. I truly believe that Microsoft was on to something with the concept of Silverlight. Like many developers, with regard to client side web development, I knew there had to be a better way to do things than JavaScript. Silverlight was a great attempt. It wasn’t perfect but the concept was good. Heck, I thought that anything that saved me from JavaScript was a good thing. I don’t care what anyone says, JavaScript is not the best solution to client side programing. I think we could have had better. Silverlight was a good try but people didn’t embrace it for various reasons (I won’t get into that in this post). Well here we are now and Silverlight is pretty much toast. It seems like Microsoft has thrown in the towel and isn’t trying to replace JavaScript and I doubt anyone else will pick up that fight.

For the past 8 months or so, I’ve been back doing “traditional” web development. I’m quite happy to be in the world of asp.net MVC with HTML, JavaScript, and CSS. In the past few years, a lot has changed. Three and a half years go, when I last did this sort of work as the main part of my job, jQuery was gaining a lot of traction and was becoming widely accepted. But not like it is today. Today, many developers incorrectly use the words JavaScript and jQuery interchangeably (which is actually quite annoying). And as great as jQuery is, there are a ton of other great JavaScript libraries to help us developers. Patterns like MVVM and SPA have gotten quite popular. And I’ve learned that there are some other great patterns that can be applied to JavaScript development that can make the experience much better, especially for a pattern-happy OO developer like me. So I have been reading up on and practicing using closures, the revealing module pattern, prototypes, MVVM, dependency injection, and more. And I haven’t even started with TypeScript which looks very interesting, to say the least. And I should also mention that products like Visual Studio (and many plugins too) have come a long way to finally embrace JavaScript and have started to treat it like a first class citizen.

In addition to the fact that doing client side development is much better these days thanks to frameworks and tooling, our users have come to expect a richer experience from web sites and applications. Users want web pages to be useable and responsive and, dare I say, “nice to use”. And so, fellow ASP.Net developers, the time for faking our way through JavaScript is over. I have put a lot of effort into learning more about JavaScript. I’ve started treating that part of my job as seriously as I do C#. I don’t expect that I’ll become some kind of JavaScript Ninja anytime soon, but I’ve realized that JavaScript enhanced UIs are an important part of my work. I’m giving JavaScript respect and I’ll expect other developers to do the same. No longer will I accept a job candidate’s dismissive answers about their knowledge of JavaScript. “Yeah, I can do a little JavaScript but I don’t like it” is no longer a valid answer to an interview question. JavaScript is an important aspect of our jobs as web developers and it isn’t going anywhere, at least not for a while.

I talk about this story a lot… few years ago in a team meeting the developers were complaining about their struggles in writing JavaScript which was becoming an important aspect of our web solution. Our manager, who is a really smart guy and still a friend of mine, asked a few questions that made a big impact on me. First he asked, “How many books have you guys read about C#?” The response varied across the team but we had all read a bunch of them. He followed that up with the knockout punch… “how many JavaScript books have you read?” The room was pretty quiet. Most of the group had read none. At least I had read one, but I was wasn’t much different than the group. JavaScript programming was part of our job but yet we didn’t take the time to learn it. And through my career I have found that most ASP.Net developer’s (myself included) experience with and towards JavaScript was pretty similar.

The age of treating JavaScript with disrespect is over. It’s a necessary part of our web solutions. And as I said earlier, the frameworks and tooling have gotten much better. So now is the time to learn it, embrace it, use it, and succeed with it.

jQuery rocks.  It makes it really easy to do cool stuff client side with JavaScript, like these cascading DropDowns (aka Select Lists).  But at the end of the day, jQuery is JavaScript, and it can still be tricky to work with.  One of these days, Visual Studio will treat JavaScript like a first class language and life will be much easier.  You’ll see that there isn’t much JavaScript here, but it took me several iterations to get this right.

I’ll start with the UI code and JavaScript.  If you want, you can read further and see the Controller code and more.

In my View, I have two DropDowns (Select Lists) and some JavaScript:

<p>
    Country:
    <%= Html.DropDownList("Countries", ViewData["Countries"] 
             as List<SelectListItem>) %>
</p>
<p>
    Region:
    <%= Html.DropDownList("Regions", new List<SelectListItem>()) %>
</p>

<script src="../../Scripts/jquery-1.3.2.js"></script>

<script type="text/javascript">
    $(function() {
        var countries = $("#Countries");
        var regions = $("#Regions");
        countries.change(function() {
            regions.find('option').remove();
            $.getJSON('/Home/Regions', { countryId: countries.val() }, function(data) {
                $(data).each(function() {
                    $("<option value=" + this.RegionId + ">" + this.RegionName + "</option>").appendTo(regions);
                });
            });
        });
    });
</script>

The Countries DropDown is pre-populated with data passed in ViewData. 

The second DropDown, Regions gets loaded when Countries changes.

Here’s how the JavaScript and jQuery stuff works…

First I get the two Select Lists, using jQuery and the ID as the selector (jQuery makes it easy!):

        var countries = $("#Countries");
        var regions = $("#Regions");

Next I wire up the change event on the Countries list to an anonymous function (jQuery makes it easy!):

        countries.change(function() {
        // ...
            });

Inside that function I do a few things.  First, find all options in the Region Select List and remove them:

            regions.find('option').remove();

Next I need to get the data for the second Select List. Guess what?  jQuery makes this easy too.  Using the getJSON() method, I supply the Controller and Action, as well as the Id of the country so I can get the correct regions.  I also declare a function to call when the JSON result comes back:

        $.getJSON('/Home/Regions', { countryId: countries.val() }, function(data) {
        // ...
        });

The last thing to do is load all of the results into the Select List.  This actually was the hardest thing to do but in the end it is very little code.  I tried using jQuery to create options and adding them to the select list.  I tried creating a list of options and setting the html value of the Select list.  I tried a bunch of stuff.  But this worked great… Iterate over the results with jQuery’s .each function and call a function for each iteration.  The function creates some dynamic html and appends it to the Region list.  I must admit, I was surprised this worked.  I’d assume that appending would put it after the select list (<select id=”Regions” />) but it actually put it inside it!

        $(data).each(function() {
            $("<option value=" + this.RegionId + ">" + this.RegionName + "</option>").appendTo(regions);
        });

That’s it!  It works great.  Of course there are more complex ways to do this, with caching etc.  This is just one way to accomplish the goal.

Here’s some code from the Controller that helps make it work.  Just remember, this is demo code.  I’m not too worried about separation of concerns and similar details. In a production app, I’d be calling more services!

In the Index Action (in this sample the Select Lists are in my Index View) I load the countries list into ViewData.  Again, this is a demo and that may not be the best practice.

    public ActionResult Index()
    {
        ViewData["Countries"] = GetCountries();
        return View();
    }

    private List<SelectListItem> GetCountries()
    {
        List<SelectListItem> countries =
            _countryList.Select(c => new SelectListItem {Text = c.CountryName, Value = c.CountryId.ToString()}).ToList();
        countries.Insert(0, new SelectListItem{ Text="", Value = "0"});
        return countries;
    }

Then I have a Regions Action that returns the JSON result with the values to add to my Regions Select List:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Regions(int countryId)
    {
        return Json(_regionList.Where(r => r.CountryId == countryId).Select(r =>
                                                                            new
                                                                                {
                                                                                    r.RegionName,
                                                                                    r.RegionId
                                                                                }));
    }

 

That covers most of it.  Happy coding.

Technorati Tags: , ,