Fork me on GitHub

Using MVVM - Model View View Model in Javascript

MVVM is an architectural pattern largely based on MVC and MVP by Microsoft, which is targeted at modern UI development by separating from the business logic and behaviour in an application. MVVM has been implemented in JavaScript in the form of structural frameworks like KnockoutJS, KendoUI MVVM and KnockbackJS.

For this post I’m going to use MVVM framework provided by Kendo but you may use any framework since implementation is going to be similar. To begin, lets put them in an order that makes sense and avoid confusion.

1. Model

Can also be called as Data Model to differentiate from View Model. It is essentially your Model (C# Class) on server.

 public class Person
 {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
 } 

2. View Model

This is essentially a javascript object with only the data required by the view. This can have fields, methods etc. To declare your View-Model use the kendo.observable function and pass it a JavaScript object:

var person = kendo.observable({
    firstName: "Prashant",
    lastName: "Chaudhary",
    fullName: function(){
        return this.get("firstName") + " " + this.get("lastName");
    }
});

kendo.bind($('#demo'), person); 

3. View

The View is the UI (a set of HTML elements) which will be bound to the View-Model.

 <div id="demo">
     First Name: <input data-bind="value: firstName" /><br />
     Full Name: <label data-bind="text: fullName" ></label>     
 </div>

Example:

Advantages & Disadvantages:

Following are some of the advantages and disadvantages as stated by the MVVm creator John Gossman himself.

Advantages:

  • MVVM Facilitates easier parallel development of a UI and the building blocks that power it
  • Abstraction of the View, reducing the amount of business logic or glue code stuck in code-behind.
  • The ViewModel is easier to unit test than code-behind or event driven code.
  • The ViewModel (being more Model than View) can be tested without concerns of UI automation and interaction

Disadvantages:

  • The overhead in implementing MVVM is “overkill” for simple UI operations
  • Whilst data-bindings can be declarative and nice to work with, they can be harder to debug than imperative code where we simply set breakpoints
  • For larger applications, generalizing the View layer becomes more difficult
  • Data binding can create a lot of book keeping. If not managed well, can result in considerable memory consumption in an application

References and Further reading:
Understanding MVVM – A Guide For JavaScript Developers by Addy Osmani
Kendo MVVM Overview

1 note

How to set up your first basic Kendo UI Grid

Now when we know how to setup a basic Kendo datasource object, our next step is to generate a Kendo UI Grid using a Kendo datasource. Grids are useful when displaying tabular data with features like sorting, paging, and grouping. Following is an example of setting up your first basic Kendo UI grid.

1. Create a placeholder for the grid

Create an empty div and assign it an id. We’ll turn this div into a grid by selecting this div via jquery selector and using .kendoGrid().

<div id="my-grid"></div>

2. Set up a Datasource for the grid

There are couple of ways to provide data to the grid

  1. Either by using an already defined sharedDataSource on the page/view that is also used by other widgets
    var sharedDataSource = new kendo.data.DataSource({
        transport: {
            read: {
                url: "http://search.twitter.com/search.json",
                dataType: "jsonp",
                data: {
                    q: function () {
                        return $('#twitter-search-text').val();
                    }
                }
            }
        }            
    });
    
    //Using the shared data source with grid
    $("#my-grid").kendoGrid({
        dataSource: sharedDataSource 
    });
    
  2. Or configuring the grid to use its own datasource
    $("#my-grid").kendoGrid({
         dataSource: { 
            transport: {
                read: {
                    url: "http://search.twitter.com/search.json",
                    dataType: "jsonp",
                    data: {
                    q: function () {
                        return $('#twitter-search-text').val();
                    }
                }
                }
            }    
         },
         selectable: false,
         groupable: true,
         sortable: true     
     });
    

3. Adding columns to the grid:

We’ll need to specify the column layout by passing an array of column definition objects to the columns property of the grid.

$("#my-grid").kendoGrid({
    columns: [ { title: "Party Id", field: "PartyId" }, 
               { title: "Name", field: "Carrier Name"}
               { title: "Description", field: "Carrier Description" } ]
});

Each column object has the following properties:

  1. title: This is the text you want to appear as the column header
  2. field: The field in the data set that this column should be bound to.
  3. template: You can specify a template for the grid column to display instead of plain text.
  4. width: The desired width of the column.

4. Configurable grid options

  • height: eg. 100 height of the grid
  • scrollable: eg. true enable scrolling in the grid in the grid
  • scrollable: eg. { virtual: true } virtual scrolling will load in data from the remote data source as you scroll down the grid
  • selectable: eg. true enable single row selection in the grid by default.
  • pageable: eg. true paging setting within the grid is controlled by the pageable attribute
  • groupable: eg. true once grouping is enabled, a new area will be exposed in the header informing you to drop a column there to group by that column

5. Working example of a Logix grid

Check the jsFiddle below to generate a dynamic grid displaying serached tweets and the users.

For further details, visit Kendo UI website.

1 note

Setting up your first basic Kendo Datasource object!

Kendo UI

The Kendo UI DataSource component is an abstraction for using local (arrays of JavaScript objects) or remote (JSON) data.

  • Supports CRUD (Create, Read, Update, Destroy) data operations
  • Supports Sorting, Paging, Filtering, Grouping, and Aggregates.

1. Creating a Datasource object

A DataSource can be created in-line with each UI widget configuration settings, or a shared DataSource can be created to enable multiple UI widgets to bind to the same, observable data collection.

  1. Creating a shared DataSource using kendo.data.DataSource that can be used by multiple UI widgets
    var sharedDataSource = new kendo.data.DataSource({
        transport: {
            read: {
                url: "/Your/Reuquest/URL", // api url            
                data: { Id: $("#someId").val() }
            }
        }
    });
    
    //Using the shared data source with grid
    $("#my-grid").kendoGrid({
        dataSource: sharedDataSource 
    });
    
    $("#chart").kendoChart({
        title: { text: "Employee Sales" },
        dataSource: sharableDataSource 
    });
    
  2. Creating in-line Datasource used by the widget
    $("#my-grid").kendoGrid({
         dataSource: { 
            transport: {
                read: {
                    url: "/Your/Reuquest/URL", // API url
                    data: { Id: $("#someId").val() }
                }
            }    
         },
         selectable: false,
         groupable: true,
         sortable: true     
     });
    

This should look familiar to you if you have been using jquery.ajax! Also since behind the scenes read passes all these options to jquery.ajax, you should still be able to use any available options with .ajax. For example: success, error callbacks, datatype, traditional etc. View more details on the Kendo website.

2. Working example:

1 note

Speed up your HTML rendering with Kendo UI Templates

Templates offer way of generating html chunks (especially repeatable) by binding to a data array or a datasource. There are multiple templating engines available on web (including jquery templates beta), however this document demonstrates the one provided by Kendo

To begin with you’ll obviously need to reference both jquery.min.js and kendo.web.min.js

1. Syntax:

JavaScript blocks are denoted by a ‘#’ on either side.

# for (var i= 0; i < data.length; i++) {#
    //some code here 
# } #

Template substitution values in the HTML are denoted by a ‘#=’ and the front and a closing ‘#’

#= item.text #

2. Creating a New Template:

You may want to create a template.kendo.js file so all your templates reside at one place and scoped to the ‘templates’ namespace. Another advantage of keeping the templates in its own separate file is browser caching speeds up the rendering.

Here’s an example of how to create a new template:

//Namespacing templates
var templates = {    
    tweet: kendo.template(
    '<a class="tweet" href="https://twitter.com/\\#!/#= from_user #/status/#= id_str #" target="_blank">'+            
        '#= text #<br/>' +                
        '<label class="weak">#= from_user # |' +
        '#= kendo.toString(new Date(Date.parse(created_at)), "dd MMM HH:mm") #</label>' +            
    '</a>'
    )
};

3. Using a Template:

You can either use these templates like templateName(data), or use kendo.render(templateName, data) for the dynamic/repeated data:

var mySingleObjectData = {
    text : "This is the text of the tweet", 
    from_user : "chaudharyp"    
};
$("#some-div").html(templates.tweet(mySingleObjectData));

var myRepeatedData = [
    {text : "This is my text", from_user : "pc"},
    {text : "This is my text", from_user : "brad"},
    {text : "This is my text", from_user : "tom"},
    {text : "This is my text", from_user : "bradley"}
];
$("#some-div").html(kendo.render(templates.tweets, myRepeatedData));

4. Check out the live demo:


For further reference, visit Kendo UI Templates demo here.

2 notes