ASP.NET MVC Display an HTML Table with Checkboxes to Select Row Items

Posted on January 5 2014 05:40 PM by jatten in ASP.NET MVC, ASP.Net, C#, CodeProject   ||   Comments (0)

6823243264_31ec905ee4Often we need to create a table for our ASP.NET MVC web application with a checkbox next to each row, in order to allow the user to select one or more items from our list for additional processing. While the concept is not terribly challenging, it is not intuitive or obvious if you are newer to MVC.

Here is one way to do it.

Image by Elif Ayiter | Some Rights Reserved

The Example Project

For our example we will simply display a list of people as rows in a table, with checkboxes to the leftmost end of each row. The user may select one or more people from the list, click a submit button, and implement some sort of processing for the individual items selected.

Our example assumes that the business model requires server-side processing of the selected items, and therefore a direct server request instead of AJAX-style processing.

You can find the working source code at my Github repo.

If you clone or download the source from Github, you will need to Enable Nuget Package Restore in order that VS can automatically download and update Nuget packages when the project builds.

Editor View Models and Editor Templates

ASP.NET MVC affords us the ability to create custom editor templates for our domain classes and models. Similar to the convention-based relationship between Controllers and Views, there is a similar convention-based relationship between Editor View Models and Editor Templates.

The MVC framework already defines its own library of Editor Templates, made available behind the scenes through methods such as EditorFor(), DisplayFor(), LabelFor(), etc. For example, when you place code like this in your view:

<div class="col-md-10">
    @Html.EditorFor(model => model.LastName)
    @Html.ValidationMessageFor(model => model.LastName)
</div>

 

MVC understands it is to retrieve the proper editor template from System.Web.Mvc.dll for a string to contain the model.LastName property on our page. The default display device will be a textbox.

Utilizing this convention, we can create a custom Editor View Template for Models or View Models within our domain which can then be used in our code. Employing an editable checkbox for each row in a table, the status of which can be sent to and from the server as a member in a list, is one case where we need to employ an Editor View Model and an Editor View Template to make things work.

How we do this becomes more clear as we step through the example code.

The Core Domain Model

For our example, we will start with a simple domain model, represented by the Person class:

The Person Model:
public class Person
{
    public int Id { get; set; }
    public string LastName { get; set; }
    public string firstName { get; set; }
}

 

Add Test Data

In order to keep our example simple, we will create a test data repository for our code to work with, so we can pretend we are working with a database. We will add the following to our Models folder:

Test Data for the Example Code:
public class TestData
{
    public TestData()
    {
        this.People = new List<Person>();
        this.People.Add(new Person() { 
            Id = 1, LastName = "Lennon", firstName = "John" });
        this.People.Add(new Person() { 
            Id = 2, LastName = "McCartney", firstName = "Paul" });
        this.People.Add(new Person() { 
            Id = 3, LastName = "Harrison", firstName = "George" });
        this.People.Add(new Person() { 
            Id = 4, LastName = "Starr", firstName = "Ringo" });
    }
    public List<Person> People { get; set; }
}

 

The above will allow us to act as though we have a backend data store.

Adding the Editor View Model

Now let's create an Editor View Model which will allow us to present each Person instance as a row in a table, and include a Selected status that we can present as a checkbox for each table row.

There are two important things to note about Editor View Models and their relationship to the Editor Template for which they are designed:

The Editor View Model class name must follow the convention ClassNameEditorViewModel

The Corresponding Editor Template must be located in a folder named EditorTemplates, within either the Views => MyClass folder, or the Views => Shared folder. We'll see more on this in a moment. For now, be aware that the naming of the View Model and the associated View is critical, as is the location of the .cshtml View file itself.

Add the following class to the Models folder. In keeping with the above, we have named our View Model SelectPersonEditorViewModel:

The Select Person Editor View Model
public class SelectPersonEditorViewModel
{
    public bool Selected { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
}

 

Looking over the code above, we see that we have included only the information required by our view, and in fact have provided only a single string property for Name. We could have included separate FirstName and LastName properties, but I decided for our list we would just display the concatenated First and Last names for each Person.

This Editor View Model will be used by MVC to render each row in our table. Now, we need to create a wrapper for the collection of rows data.

Adding the Wrapper View Model

We need a wrapper to contain a list of the EditorViewModels we wish to pass to and from our View. Also, we will include a method which gives us handy access to a list of the Ids of the items where the Selected property is true:

The People Selection View Model:
public class PeopleSelectionViewModel
{
    public List<SelectPersonEditorViewModel> People { get; set; }
    public PeopleSelectionViewModel()
    {
        this.People = new List<SelectPersonEditorViewModel>();
    }
    public IEnumerable<int> getSelectedIds()
    {
        // Return an Enumerable containing the Id's of the selected people:
        return (from p in this.People where p.Selected select p.Id).ToList();
    }
}

 

As convoluted as this may sound, what we do is use the PeopleSelectionViewModel to wrap an IEnumerable of SelectPersonEditorViewModel items, and pass this to out primary view. Now let's take a look at the views we will need to make this work.

Create an Editor View Template

Here is where we start to bring this all together. As mentioned previously, we need a custom Editor View Template in order to pass our individually selectable row data to and from our main view. We can locate individual Editor Templates in a folder named EditorTemplates nested in either the Folder specific to the main view in question (in this case, Views => People => EditorTemplates) or within the Views => Shared folder (which then makes the Editor Template available to the entire application).

In the current case, we will add an EditorTemplates folder to the Views => People folder, since this is a rather special purpose template, specific to the People controller.

Add an Editor Templates Folder to the Appropriate Directory:

add-the-editor-templates-folder

Now, let's add our Editor Template View. Right-Click on the new folder, add a new View, and name it very specifically SelectPersonEditorViewModel, so that the name matches the name of the actual View Model we created earlier. Then add the following code:

The Select Person Editor View Model View:
@model AspNetCheckedListExample.Models.SelectPersonEditorViewModel
<tr>
    <td style="text-align:center">
        @Html.CheckBoxFor(model => model.Selected)
    </td>
    <td>
        @Html.DisplayFor(model => model.Name)
    </td>
    <td>
        @Html.HiddenFor(model => model.Id)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
        @Html.ActionLink("Details", "Details", new { id = Model.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id = Model.Id })
    </td>
</tr>

 

The Editor Template View above provides display items for the relevant model data, as well as en editor for the checkbox, and a hidden element for the mode.Id property. We will use this Id property, and the value of the Selected property to determine which people the user has selected for additional processing when the list of View Models is returned from the view in an Http POST request.

Adding the Index View

Also in the Views => People folder, add a new Empty View named Index. This is the main View we will use to contain our table of People. Once the view has been added, add the following code:

The People Index View:
@model AspNetCheckedListExample.Models.PeopleSelectionViewModel
  
@{
    ViewBag.Title = "People";
}
  
<h2>People</h2>
  
@using (Html.BeginForm("SubmitSelected", "People", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
{
    <table class="table">
        <tr>
            <th>
                Select
            </th>
            <th>
                Name
            </th>
            <th></th>
        </tr>
        @Html.EditorFor(model => model.People)
    </table>
    <hr />
    <br />
    <input type="submit" name="operation" id="submit" value="Submit Selected" />
}

 

As you can see in the above, we have created a basic HTML Form, and within that have defined a table. The table headers are clearly laid out within this view, but we can see that where we would ordinarily populate our rows using a foreach() construct, here we simply specify @Html.EditorFor() and specify the the IEnumerable<SelectPersonEditorViewModel> represented by the People property of our Model.

Tying it all together - the People Controller

Of course, none of this means anything without the Controller to govern the interaction of our Views and Models. For our ultra-simple project, we are going to define an ultra-simple controller, which will include only two Action methods: Index, and SubmitSelected.

Add a controller to the controllers folder, appropriately named PeopleController, and add the following code:

The People Controller Class:
public class PeopleController : Controller
{
    TestData Db = new TestData();
  
    public ActionResult Index()
    {
        var model = new PeopleSelectionViewModel();
        foreach(var person in Db.People)
        {
            var editorViewModel = new SelectPersonEditorViewModel()
            {
                Id = person.Id,
                Name = string.Format("{0} {1}", person.firstName, person.LastName),
                Selected = true
            };
            model.People.Add(editorViewModel);
        }
        return View(model);
    }
  
  
    [HttpPost]
    public ActionResult SubmitSelected(PeopleSelectionViewModel model)
    {
        // get the ids of the items selected:
        var selectedIds = model.getSelectedIds();
        // Use the ids to retrieve the records for the selected people
        // from the database:
        var selectedPeople = from x in Db.People
                             where selectedIds.Contains(x.Id)
                             select x;
        // Process according to your requirements:
        foreach(var person in selectedPeople)
        {
            System.Diagnostics.Debug.WriteLine(
                string.Format("{0} {1}", person.firstName, person.LastName));
        }
        // Redirect somewhere meaningful (probably to somewhere showing 
        // the results of your processing):
        return RedirectToAction("Index");
    }
}

 

In our Index method, we pull a List of Person instances from our database, and for each instance of Person we create an instance of SelectPersonEditorViewModel. Note that for our example application, I have decided that the default value of the Selected property will be set to true, as it is most likely the user will process the entire list.

We then load each instance of SelectPersonEditorViewModel into our PeopleSelectionViewModel, and then pass this to the Index View itself.

Processing the Selection Results in the Submit Selected Method

When the user submits the form represented in our index view, the model is returned in the POST request body. Note the we needed to decorate the SubmitSelected method with the [HttpPost] attribute. We then use the getSelectedItems() method we added to our PeopleSelectionViewModel to return a list of the selected Ids, and use the Ids to query the appropriate records from our database.

In the example, I obviously am just writing some output to the console to demonstrate that we have, indeed, returned only the selected items from our View. Here is where you would add your own processing, according to the needs of your business model.

Adding a Select All Checkbox to Toggle Selected Status

Commonly in this scenario, we would want to afford our user the ability to "Select All" the items in the list, or "Select None" of the items. The JQuery code for this has been added to the project source, and you can read more about how to do this in Adding a Select All Checkbox to a Checklist Table Using JQuery.

Modifications to Make the Demo Project Run (not required)

In order make the example project work, I went ahead and made the following modifications to the rest of the standard MVC project. The following is not really related to creating a table with checkboxes, but might help if you are following along and building this out from scratch instead of cloning the project from Github.

Make the Index View of the People the Default Home Page

In the <body> section of the shared _Layout.cshtml file (Views => Shared => _Layout.cshtml) I removed the tabs for Home, Contact, and About, and added a tab for People, pointing at the Index method of the People Controller. The revised <body> section now looks like this:

Modified Body Section of _Layout.cshtml:
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "People", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("People", "Index", "People")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>
  
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>

 

Update the Route Configuration

Also, I modified the Route.config so that the default route points to the Index method of the People Controller, instead of Home. The modified Route mapping looks like this:

Modified Route Mapping:
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "People", action = "Index", id = UrlParameter.Optional }
);

 

Remove Unneeded Controllers and Views

For the demo project, I had no need for the extra controllers and views included with the default MVC project, so I removed them. We can delete the Home Controller, as well as the Home folder in the Views directory.

Additional Resources and Items of Interest

 

Posted on January 5 2014 05:40 PM by jatten     

Comments (0)

ASP.NET MVC: Add a Select All Checkbox to a Checklist Table Using JQuery

Posted on January 5 2014 05:40 PM by jatten in ASP.NET MVC, ASP.Net, C#, CodeProject   ||   Comments (0)

jQuery-CSS-LogoOften, we find we need to present our users with a list of items in a table or list, with checkboxes such that the user can select one or more items from the list for additional processing. Most of the time, the user will either be selecting a few items from the list but leaving most unchecked, or selecting all or most of the items from the list and leaving very few items unchecked.

In these cases, it is handy to offer the user a means to "Select All" or "Select None" which then toggles the checked state of the entire list. The common means to do this is with one more checkbox, global to the list itself, which performs the toggling action.

One way to do this is to use JQuery.

The Example Project

We will use an existing example project I created to demonstrate how to display a table with checkboxes for each row, which allows submission to the server for processing the selected items. Here, we will focus on the selection toggling portion of the Index View.

You can find the source code for the example project on my Github repo.

If you clone or download the source from Github, you will need to Enable Nuget Package Restore in order that VS can automatically download and update Nuget packages when the project builds.

The Index View, with Selectable Items in a Table

For our purposes, we will only need to look at the Index view, which presents a table where each row features a checkbox on the leftmost side allowing the user to select one or more individual row items from the list.

The original code for the View looks like this:

Index View with a Table and Checkboxes:
@model AspNetCheckedListExample.Models.PeopleSelectionViewModel
  
@{
    ViewBag.Title = "People";
}
  
<h2>People</h2>
  
@using (Html.BeginForm("SubmitSelected", "People", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
{
    <table class="table">
        <tr>
            <th>
                Select
            </th>
            <th>
                Name
            </th>
            <th></th>
        </tr>
        @Html.EditorFor(model => model.People)
    </table>
    <hr />
    <br />
    <input type="submit" name="operation" id="submit" value="Submit Selected" />
}

 

In the above, we set up a table, and use a custom Editor Template to render each row item, allowing for the selectable textbox on each row, the status of which will be reflected in the model data passed back to the controller in an Http POST request on form submit.

We want to add a checkbox above the table, selection of which toggles the checked status of all the checkboxes in the table at once.

Add the Select All Checkbox

To do this, we will modify the form on our Index page by adding a <div> element containing our global checkbox, which we will name "checkall", and then also wrap our Html table in a div named "checkboxes" that we can then manipulate using JQuery:

Add Div Elements to HTML Form on the Index Page:
@using (Html.BeginForm("SubmitSelected", "People", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
{
    // Add a new checkbox in its own div element:
    <div>
        <input type="checkbox" id="checkall" /><span>Check All</span>
    </div>
  
    // Wrap the table element in a div named "checkboxes":
    <div id="checkboxes">
        <table class="table">
            <tr>
                <th>
                    Select
                </th>
                <th>
                    Name
                </th>
                <th></th>
            </tr>
            @Html.EditorFor(model => model.People)
        </table>
    @*Close the "checkboxes" div element:*@
    </div>
    <hr />
    <br />
    <input type="submit" name="operation" id="submit" value="Submit Selected" />
}

 

JQuery Code to Manipulate the Checkboxes

Now we will add some JQuery to perform the manipulation when we want to toggle the checkbox status. For simplicity, we are going to add this code right on our page. Note that there are myriad ways to do this, and you may see some methods out on the internet which are slightly different.

Under our view code, we will add a <scripts> section, and add the following JQuery:

Add JQuery to Toggle the Checkbox Status for the Table Row Items:
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
  
    <script type="text/javascript">
  
        function toggleChecked(status) {
            $("#checkboxes input").each(function () {
                // Set the checked status of each to match the 
                // checked status of the check all checkbox:
                $(this).prop("checked", status);
            });
        }
  
        $(document).ready(function () {
  
            //Set the default value of the global checkbox to true:
            $("#checkall").prop('checked', true);
  
            // Attach the call to toggleChecked to the
            // click event of the global checkbox:
            $("#checkall").click(function () {
                var status = $("#checkall").prop('checked');
                toggleChecked(status);
            });
        });
    </script>

 

In the above code, We define a function, toggleChecked() , which sets the checked status of each checkbox in the table to match that of the global "checkall" checkbox. Then, in the JQuery (document).ready() function, we the default value of the global "checkall" checkbox to true, and attach a call to the toggleChecked() function to the click event of the global "checkall" checkbox.

As we can see, it is not a complex matter to do this, but it may not be intuitive to those newer to Jquery.

As I mentioned, there are myriad ways to do this out there on the web. if you have seen a better way, or noticed something I have done above that it just plain stupid, please do let me know in the comments, or drop me an email at the address in the About the Author section.

Additional Resources and Items of Interest

 

Posted on January 5 2014 05:40 PM by jatten     

Comments (0)

Is Duck Typing a Type System, or a Way of Thinking?

Posted on January 4 2014 10:43 AM by jatten in CodeProject, C#, Javascript   ||   Comments (4)

6114395629_e28c3d1c65Ok, so there is what might be my first-ever "link bait" title. Especially dangerous because I am about to jump into a discussion propagated by some well-known, highly-respected developers against whom my own self-taught, inexperienced knowledge pales. 

I lack the formal schooling or training to join this discussion at the academic level, I simply know what I think I know, and will attempt to toss my opinion out there and see what happens. Actually, that is another first for me . . . I normally recognize that I don't have sufficient "real-world" experience or education to express a strong opinion on such things. Must be early Saturday morning, and I might need more coffee.

Image by Federico Reiven | Some Rights Reserved

Eric Lippert recently posted a typically well-stated article on his blog, Fabulous Adventures in Coding (if you don't already subscribe, now would be a perfect time to do so. His stuff really is THAT GOOD), setting out his thoughts relating Duck Typing to what we in the statically-typed world might recognize as Late Binding. When I woke this morning, I found in my inbox from Phil Haack's blog feed a follow-up in which aptly uses the square filters/round holes issue from the ill-fated Apollo 13 mission as an analogy for Duck Typing.

Both Lippert and Phil Haack appear to be attempting to reconcile the concept of Duck Typing with static type systems, and statically typed programming practices.

Mr. Haack appropriately pulls out some python code, but in my humble opinion only brings the Duck Typing concept partway home, by looking at method overriding in dynamically-typed languages as an example of how Duck Typing might be effectively demonstrated. Most importantly, Phil Haack hits on what, to me, is the deciding gem of the quest to understand:

"I think some of the confusion lies in the fact that duck typing isn't so much a type system as it is a fuzzy approach to treating objects as if they are certain types (or close enough) based on their behavior rather than their declared type. This is a subtle distinction to late binding."

-Phil Haack

Unfortunately (for me, anyway) he then goes on to discuss Duck Typing from a perspective of method overloading. Obviously, Phil Haack knows of which he speaks, and I in no way disagree with what he is saying. However, for myself, the important way to look at Duck Typing is unnecessarily obscured from this perspective.

My question is, are we trying too hard to pigeonhole a simpler concept?

Developers Moving from Statically-Typed to Dynamically-Typed Languages Tend to Over-Complicate Things

As one who has spent most of my time coding in a statically-typed language, I have developed some very basic coding practices and ways of thinking which make the transition to a dynamic approach most challenging. The mushy, malleability of dynamic languages and typing creates a situation which forces us to re-examine what we think we know about type systems, method signatures, and such (at least, if we come from a statically-typed background).

I have spent a lot of time trying to reconcile the dynamic mushiness with my static-typed tendency to create code which, through the action of compile-time type checking, forces the client of my code to "do the right thing."

If we examine some simple, but common design strategies in C# code, we can understand this tendency.

Interfaces Mimic the Notion of Duck-Typing in Statically-Typed Languages

When working in C#, Java, or other statically-typed language paradigm, we become very accustomed to working within the type system, and not only allow it to dictate much of our program structure, but also to assist us in protecting clients of our program from doing the wrong thing.

void TheAnimalSpeaks(Animal animal)
{
    Console.WriteLine(animal.WhatISay);
}

 

Before the code above will even compile, there are three things, at a minimum, which must be satisfied:

  • There must be an Animal class defined, and available to our code
  • The argument passed in to the method TheAnimalSpeaks must be of class Animal
  • The Animal class must itself define a WhatISay Property which resolves to a string

Therefore, we would need, at a minimum, a class Animal, which includes a property WhatISay:

The Animal Class:
class Animal
{
    public string WhatISay { get { return "I Said Something"; } }
}

 

In the C# world, we now know that any client code which wished to call the method TheAnimalSpeaks will be providing an instance of Animal as an argument, and that instance will indeed make available a property named WhatISay. We know this because the client code will not even compile until it does these things.

Also in C#, if we wanted to define different sorts of animals which all share some common behaviors and properties, we could define an IAnimal Interface, which would need to include the property WhatISay, and then modify our method TheAnimalSpeaks to accept an instance of IAnimal as an argument:

The IAnimal Interface in C#:
interface IAnimal
{
    string WhatISay { get; }
}

 

We would then Implement the IAnimal interface on any class we wished to exhibit the property WhatISay:

Classes Implementing the lAnimal Interface in C#:
class Duck : IAnimal
{
    public string WhatISay { get { return "Quack"; } }
}
  
  
class Wolf : IAnimal
{
    public string WhatISay { get { return "Howl"; } }
}
  
  
class Toaster : IAnimal
{
    public string WhatISay { get { return "Hi, I'm not even an animal!"; } }
}

 

Now, we can pass any instance of IAnimal to our method TheAnimalSpeaks and it will work. The compiler will make certain for us that, before we can even run our program, any code which calls this method is passing an argument which implements IAnimal.

static void Main(string[] args)
{
    // We can explicitly declare an instance of IAnimal . . .
    IAnimal theBigBadWolf = new Wolf();
    TheAnimalSpeaks(theBigBadWolf);
  
    //  . . . OR we can explicitly declare an instance 
    // of any type which IMPLEMENTS IAnimal:
    var theFleeingDuck = new Duck();
    TheAnimalSpeaks(theFleeingDuck);
}
  
static void TheAnimalSpeaks(IAnimal animal)
{
    Console.WriteLine(animal.WhatISay);
}

 

In the code above, we can either explicitly declare an instance of type IAnimal, or we can simply instantiate a type which implements the IAnimal interface, and our code will compile and run. We can also see that, so long as a class implements the IAnimal interface, it matters not what the actual class represents (as we can see from the Toaster class, which presumable has little or nothing to do with animals, but can still be passed to the method TheAnimalSpeaks, even though it is not necessarily a good example of domain modelling!).

This is Interface Inheritance 101, Dude. WTF, and Why Do I Care?

As a developer with a lot of background in a statically-typed environment, I found the transition to the dynamic world of JavaScript most challenging. In statically-typed land, we learn to expect that our method signatures, and compiler type checking will protect consumers of our code from passing in the wrong arguments.

In other words, the compiler enforces the contracts established by the method signatures we devise, and we carefully create our domain models to work within these boundaries. We devise  base classes and interfaces to define type expectations at program boundaries, and sleep well at night knowing that client code can't even call into our methods until certain minimum conditions are met.

When we move into a dynamically-typed environment, all that goes out the window.

Dynamically-typed languages do not perform any compile-time type-checking, instead relying on a run-time type system as described by Eric Lippert so effectively. All of the Type definition and interface business we discussed previously has little meaning in such an environment, because none of the advantages afforded by interfaces and the contracts they provide for the compiler are realized.

Duck Typing in Dynamic Languages

In my under-educated understanding, it seems to me common dynamic languages utilize Duck Typing implicitly. If seems to me we go to great lengths to describe a concept which should be fairly simple at its core:

From the Wikipedia definition referred to by Lippert:

"duck typing is a style of typing in which an object's methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface."

More Explicitly:

"In duck typing, one is concerned with just those aspects of an object that are used, rather than with the type of the object itself. For example, in a non-duck-typed language, one can create a function that takes an object of type Duck and calls that object's walk and quack methods.

In a duck-typed language, the equivalent function would take an object of any type and call that object's walk and quack methods. If the object does not have the methods that are called then the function signals a run-time error. If the object does have the methods, then they are executed no matter the type of the object, evoking the quotation and hence the name of this form of typing."

I have little background in compiler design, and I accept as axiomatic that under the covers, behind the scenes, there is a whole lot going on under the hood in the implementation of both the C# compiler, and the JavaScript interpreter to make both type systems work properly.

Duck Typing in JavaScript

However, to understand Duck Typing at the useful level of abstraction required to write code, the above definition can be illustrated by contrasting the previous C# examples with some simple JavaScript:

Let's consider some similar code in JavaScript. Note that JS does not have any notion of "classes." I will, however, model up some similar constructs using the JavaScript Module pattern (I am using the Node.js runtime here, such that I can execute the code in the terminal).

First, let's look at a Duck module:

A Duck "Class" (Module) in JavaScript:
var Duck = function() {
  this.whatISay = "Quack";
};
  
module.exports = Duck;

 

Here, we have defined a module which returns a "duck" object. We can do the same for our Wolf "class":

A Wolf "Class" (Module) in Javascript:
var Wolf = function() {
  this.whatISay = "Howl";
};
  
module.exports = Wolf;

 

Now, let's write a method analogous to our C# method TheAnimalSpeaks, and execute it in the terminal using Node.js:

Running the Javascript Equivelent Code:
var Duck = require("./Duck");
var Wolf = require("./Wolf");
  
this.theAnimalSpeaks = function(animal) {
  console.log(animal.whatISay);
};
  
var myDuck = new Duck();
this.theAnimalSpeaks(myDuck);
  
var myWolf = new Wolf();
this.theAnimalSpeaks(myWolf);

 

When we run the code above, the output in the terminal is, predictably:

Terminal Output from theAnimalSpeaks method in JavaScript:
Quack
Howl

 

As we can see, the JavaScript method theAnimalSpeaks cares not one whit what kind of object we pass in to it. In fact, it doesn't really recognize the argument's type until runtime, and even then, only recognizes that it is to look for a property on the passed in argument named whatISay. If it finds such a property, it will attempt to use it. If not, it will return the value undefined. If, instead of a property we were attempting to access a method, the JS runtime would throw a runtime error indicating that no such function exists.

Not Duck Typing in Javascript

Let's make a JavaScript analog of our Toaster class, but let's give it some sort of "toaster-like" method, and not include the whatISay property:

The JavaScript Toaster "Class" (Module):
var Toaster = function() {
  this.startToast = function(minutes) {
    console.log("the toast will cook for " + minutes + " minutes");
  };
};
  
module.exports = Toaster;

 

Here, we have created a "class" with a single method - the startToast() function which accepts an argument specifying how long to cook the toast. If we modify our application code to call into the Toaster module, attempting to both access the whatISay property as well as call the startToast() method, we see in the terminal output that the attempt to access the non-existent property returns undefined, and the call to startToast() executes as expected.

ApplicationCode Consuming the Toaster "Class" (Module):
var Duck = require("./Duck");
var Wolf = require("./Wolf");
var Toaster = require("./Toaster");
  
this.theAnimalSpeaks = function(animal) {
  console.log(animal.whatISay);
  animal.startToast(4);
};
  
var myToaster = new Toaster();
this.theAnimalSpeaks(myToaster);  

 

The terminal output from the above is:

Terminal Output from Application Code Consuming the Toaster "Class" (Module):
undefined
the toast will cook for 4 minutes

 

Obviously, the above is NOT an example of effective Duck Typing, as we are mixing metaphors and domain objects here. In similar fashion, let's try to pass one of our animal objects into the code as it currently exists:

Passing a Duck object into the Modified Application Code:
var Duck = require("./Duck");
var Wolf = require("./Wolf");
var Toaster = require("./Toaster");
this.theAnimalSpeaks = function(animal) {
  console.log(animal.whatISay);
  animal.startToast(4);
};
  
var myDuck = new Duck();
this.theAnimalSpeaks(myDuck);

The code above throws an error informing us that the object has no method startToast().

If it Acts Like a Duck, and Quacks Like a Duck, we can Use it like a Duck

The contrived examples above partially illustrate the power and danger in the Duck Typing concept. We have taken a method which accepts an argument, animal, and attempts to access certain properties and/or methods that it expects to find. There is nothing in the method "signature" beyond the name of the argument to tell us what methods and properties are expected, and the compiler is not going to help us prior to runtime. But if that object presents the expected properties/methods called by the code, all is well.

This is in keeping with the Wikipedia definition:

"duck typing is a style of typing in which an object's methods and properties determine the valid semantics . . ."

Let's look at one more silly example of how Duck Typing might be of use (or danger, as the case may be).

Modifying an Object at Runtime to take a Duck Typed Approach

Returning to our application code, lets ditch the call to the startToast() method, which we used previously only to illustrate how calling a non-existent function throws an error. Let's instead return to the idea that the method theAnimalSpeaks() expects to receive an argument animal, and that it expects the animal to have a property named whatISay which returns a string:

The Original Application Code:
var Duck = require("./Duck");
var Wolf = require("./Wolf");
var Toaster = require("./Toaster");
  
this.theAnimalSpeaks = function(animal) {
  console.log(animal.whatISay);
};
  
var myDuck = new Duck();
this.theAnimalSpeaks(myDuck);
  
var myWolf = new Wolf();
this.theAnimalSpeaks(myWolf);

 

Now, let's take things one more step in the direction of the ridiculous. Let's modify our myToaster object instance at runtime, adding a property whatISay, and then passing it to the method TheAnimalSpeaks:

Modified Application Code using a Duck Typed Approach:
var Duck = require("./Duck");
var Wolf = require("./Wolf");
var Toaster = require("./Toaster");
  
this.theAnimalSpeaks = function(animal) {
  console.log(animal.whatISay);
};
  
var myDuck = new Duck();
this.theAnimalSpeaks(myDuck);
  
var myWolf = new Wolf();
this.theAnimalSpeaks(myWolf);
  
var myToaster = new Toaster();
myToaster.whatISay = "I'm not an animal, but I speak and make toast";
this.theAnimalSpeaks(myToaster);   

 

Terminal output from the example above is:

Terminal Output from Modified Application Code:
Quack
Howl
I'm not an animal, but I speak and ost

 

Here we have, for better or worse, seen the idea of Duck Typing in action. We passed three different objects to our method theAnimalSpeaks. In all three cases, the object looked and acted like what the code was expecting, and so the runtime was able to properly execute the method.

In the case of the toaster, we forced the object to "look and act" like an animal for the purposes of our method call.

As our Wikipedia definition says:

" [. . . a Duck Typed] function would take an object of any type and call that object's walk and quack methods . . . If the object does have the methods, then they are executed no matter the type of the object . . ."

Is Duck Typing a Type System, or a Way of Thinking?

To me, as I try to write better, more idiomatic JavaScript code (I have a long, long way to go here), I find for the moment that learning to "think duck typing" is more valuable than attempting to define it in terms I relate to static type systems.

I am not sure one can say that a Duck Typing represents a Typing System per se. One might instead subscribe to the notion that to varying degrees, certain dynamic languages afford us the ability to employ a Duck Typed approach.

One line in the Wikipedia Entry that is not given the attention I feel it deserves by mssr.'s Lippert or Haack is:

"Duck typing is aided by habitually not testing for the type of arguments in method and function bodies, relying on documentation, clear code and testing to ensure correct use."

This has been my experience when working with JavaScript so far. You want to call a method, you need to figure out what it expects as arguments, and make sure whatever you are passing in has the properties and/or methods expected by the method implementation. And THAT'S IT.

To my mind, JavaScript (as an example) allows us to design a method which accepts an argument of whateverTheHellIWant, and the code will run properly so long as the argument implements the properties and behaviors expected by the method code.

Obviously to me, we want to adhere to some pretty solid design and naming conventions here. Additionally, there is probably no more clear case for effectively documenting an API such that consumers can more easily understand what is expected when calling your code.

In Dynamic Languages, the Interface is Implicit

Another way to approach the idea is to return to our concept of the interface in statically-typed systems. In these cases, and in our C# examples at the beginning of this article, we can see that interfaces in a statically-typed scenario allow us to say "This object looks and acts like a duck" even if it is not.

In a dynamic language, the ceremony associated with compile-time type checking, interface declaration, and such is unneeded. There is no compiler to enforce the type system rules, or to make sure our object implements a particular interface. This affords us an exceptional degree of freedom in designing our application code, and also places on us, the developer, the responsibility for ensuring our code will function correctly.

Final Thoughts

The preceding was inspired by both my own quest to better understand the languages I am using, and by reading two articles by developers I admire, and who know better than me. If anyone thinks I am trying to argue the points they make, please understand I am not. I am merely trying to synthesize what those two luminaries wrote with my own understanding, at the level that works best for me. If it helps anyone else, so much the better.

I am new to the world of Dynamic Languages in general, and JavaScript specifically. I am not a compiler builder, nor do I have any sort of academic training in language design.

Additional Resources and Items of Interest

 

Posted on January 4 2014 10:43 AM by jatten     

Comments (4)

About the author

My name is John Atten, and my "handle" on many of my online accounts is xivSolutions. I am Fascinated by all things technology and software development. I work mostly with C#, JavaScript/Node, and databases of many flavors. Actively learning always. I dig web development. I am always looking for new information, and value your feedback (especially where I got something wrong!). You can email me at:

jatten at typecastexception dot com

Web Hosting by