notoriousb1t

MVP Part 4: KendoUI

Background

After a few week hiatus, I'm ready to continue Model View Pizza. My aim in this project is to show ten or more JavaScript MVVM/MVC Frameworks side by side for the same application. While I am primarily doing this for self-enrichment, I thought it would be a good idea to write about the frameworks. Here is a link to a demo of KendoUI Project, and there is a link to the source code on GitHub

About Kendo UI

Kendo is a JavaScript framework that has a wide range of rich controls that can do anything from turning an input into a proper datepicker to connecting to a remote 'odata' datasource and rendering it in a pivot grid. Hands down, it is incredibly powerful when used with a server side framework like ASP.NET MVC.

I have used some of their MVVM bindings in the past to initialize their web controls, but have never used it to build a Single Page Application. Telerik, the company that owns Kendo UI, has open-sourced the core of their framework, so I will be using the minified file from that distribution. For the purposes of Model View Pizza, I am focusing on the MVVM part of the framework and won't use the rich controls.

Documentation

It turns out that this was not a framework I could just muddle through. Good examples of just the MVVM part of the framework aren't exactly exploding from the internet. I speculate that this is because it is rarely used without the web controls. I wasn't able to navigate to the docs for Kendo MVVM in Telerik's main site quickly, so I ended up searching "kendo mvvm" on google which linked to the Kendo MVVM Overview.

A Simple Example

Here is a simple example of Kendo UI MVVM:

    <form id="content">
        <div>
            <label>Name</label>
            <input data-bind="value: name" type="text" />
        </div>
        <div>
            <label>Age</label>
            <input data-bind="value: age" type="number" />
        </div>
        <button data-bind="click: submit">Submit</button>
    </form>
    var viewModel = kendo.observable({
        name: 'John Smith',
        age: 32,
        submit: function() {
            var name = this.get('name');
            var age = this.get('age');
            var message = name + ' is ' + age + ' years old';

            console.log(message)
        }
    });

    kendo.bind($('#content'), viewModel);

In the html above, I am marking each element with the data-bind attribute. The format of the binding expression is "name: expression" with each binding separated by a comma. I am using the value binding to bind to the inputs and the click binding to bind to the click event of the button.

In the JavaScript above, I am passing an object with name, age, and submit properties to kendo.observable which in turn creates an ObservableObject. This ObservableObject is then bound to a JQuery element. It seems like Kendo was inspired in large part by KnockoutJS.

Implementation

I did not have too much trouble porting the KnockoutJS code to KendoUI code, but so far it was the most challenging. There were, however, two things in particular that got on my nerves.

Accessing By String

I know of only a couple of ways to monitor property changes in an object and fire an event.

  1. Use some kind of polling mechanism that checks all the values against the previous values. I think that AngularJS 1 uses something like this.
  2. Fire an event each time the property is set. VueJS uses this methodology by overriding the get/set accessor methods in each model property.
  3. Set a "dirty" flag when a property changes and then use polling to fire the event when that flag is detected. I don't know of any JS libraries that do this, but it is essentially a hybrid of the first two.

KendoUI also uses the second, but instead of overriding the accessors, it adds a get/set method to the model that use the name of the property to set/get the values.

The first issue I have with programming this way has to do with tooling. For example, consider the following two pieces of code:

The actual code

    this.set('firstName', 'Tom');

The intended code

    this.firstName = 'Tom';

Visual Studio, Sublime, etc. wouldn't know that firstName is a property of this. Because of this, if I wanted to automatically refactor firstName, the IDE won't know to change the name in a string. I would have to limit the use of this standard IDE function because of the risk.

The second issue is with using shorthand operators. Take this short piece of code:

    function incrementParty() {
        this.partyCount++;
    }

That piece of code now becomes the following code in KendoUI:

    function incrementParty() {
        this.set('partyCount', this.get('partyCount') + 1);
    }

One requirement I have for JavaScript frameworks is that it should be easy to write natural readable code. Having to use get/set all the time is not going to enable me to do that. From a compatibility point of view, I understand why they chose this route, I just can't dig it, though.

Subviews through Templates

In each of the frameworks I have reviewed so far, they provided nested views through a type of "foreach" binding. The HTML inside the element marked with that element is given a scope to the sub-properties of the property in the binding. In pseudo-code:

    <div data-bind="foreach: persons">
        <span data-bind="text: firstName"></span>
    </div>

In the pseudo-code above, each person in persons has a firstName property. I can access each firstName inside of the scope of the div. KendoUI does it a little differently, however:

    <div data-bind="source: persons" data-template="personItemTemplate"></div>
    <script type="text/template" id="personItemTemplate">
        <span data-bind="text: firstName"></span>
    </script>

` The biggest benefit of separating the subviews into templates is that it encourages reusing that piece of HTML. I would say the biggest drawback is that it physically separates two related pieces of markup that may not have an opportunity to be reused. While I don't see this strategy as being inherently negative, it did make reviewing my code a little harder than it had to be.

Summary

Overall, I did not like working with the MVVM part of the framework. As a general use MVVM framework, there were just too many issues where I had to really hunt for the answer or the way to do simple things felt strange.

That being said, from experience I can say that the web controls really shine and are great when used in conjuction with AngularJS 1 or when used with a server side MVC framework. I would not recommend using this MVVM framework, but I would still recommend using their web controls in business applications.