Friday, March 15, 2013

Computing Unions With Lodash and Knockout

It's easy to create observable arrays using Knockout. We can even create computed observables that are based on those arrays. For example, a computed observable might return the last item in the array. This means that any bindings for this computed observable will update any time the array changes. Specifically, the last item in the array. Where the observable arrays get interesting are when there are several of them, and you have a computed observable based on each array. Say, for example, we have several arrays that store programming language names, based on category. There may be some overlap between arrays since many languages are multi-faceted. This is where we can utilize Lodash in out computed observables.

Here is an example binding for the union of all programming languages.

<h4>Laguages</h4>
<ul data-bind="foreach: languages">
    <li data-bind="text: $data"></li>
</ul>

And here is the model, with several programming language arrays. The languages property is a computed observable where we're using _.sortBy() and _.union() to return an array of all unique programming language names.

function LanguageModel() {

    this.objectOriented = ko.observableArray([
        "C++",
        "Java",
        "Lua",
        "PHP",
        "Python",
        "Ruby",
        "Smalltalk"
    ]);

    this.procedural = ko.observableArray([
        "Ada",
        "C",
        "C++",
        "COBOL",
        "JavaScript",
        "Go",
        "Java",
        "Python"
    ]);

    this.reflective = ko.observableArray([
        "C#",
        "Java",
        "Lisp",
        "Lua",
        "Prolog"
    ]);

    this.scripting = ko.observableArray([
        "AWK",
        "Bash",
        "Groovy",
        "Python"
    ]);

    this.languages = ko.computed(function() {
        return _.sortBy( _.union(
            this.objectOriented(),
            this.procedural(),
            this.reflective(),
            this.scripting()
        ));
    }, this );

};

ko.applyBindings( new LanguageModel() );