Kendo UI Cookbook

By Sagar Ganatra
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. The Kendo UI Application Framework

About this book

Kendo UI is a one-stop library that allows you to build applications for web and mobile platforms using HTML5 and JavaScript. The library includes several widgets that allow you to build compelling web applications rapidly. Building web applications for web and mobile platforms using modern web technologies is now easy with the Kendo UI library. This cookbook contains practical recipes that you can apply in your everyday projects, and build compelling applications effortlessly. It gets you started with the application framework and then guides you through various widgets that you can readily use in your project with minimum configuration. It also provides recipes that you can use to build web applications for various mobile platforms while maintaining a single codebase.

Publication date:
June 2014
Publisher
Packt
Pages
250
ISBN
9781783980000

 

Chapter 1. The Kendo UI Application Framework

In this chapter, we will cover the following recipes:

  • Using client-side templates to generate HTML markup from JSON data

  • Creating a two-way binding between View elements and JavaScript objects using the Model View ViewModel (MVVM) pattern

  • Using source and template binding with ViewModel to generate HTML content

  • Validating user input using the built-in Validator

 

Introduction


The Kendo UI library is composed of various widgets that are built for both the web and mobile platform. It also provides data visualization components, which can be used to build rich and interactive charts. This chapter focuses on the Kendo UI application framework. This framework includes tools such as the client-side templating engine, data binding, and routing, and it also helps users to validate form fields.

 

Using client-side templates to generate HTML markup from a JSON data


The concept of using a templating system with some data source to generate a dynamic web content has been around web development for a long time. Java Server Pages (Java), Smarty (PHP), and Django (Python) are examples of some of the server-side templating engines. Generating content at runtime used to be a server-side-only affair. In recent years, generating the content on the client side (on the browser) has been embraced.

The dynamic applications that are being built today require the user interface to be updated frequently. This can be achieved by fetching the HTML fragment from the server and then inserting it into the document. However, this requires the server to generate such fragments as opposed to delivering complete web pages. In the client-side templating engine, the servers are responsible for sending only the dynamic data in the JSON format and then have the page assembled in the browser using a static client-side template. This template can be served from Content Delivery Network (CDN) instead of the same server that sends the dynamic data. The time taken to send the records in the form of JSON data and not generate the markup on the server side takes away more CPU cycles, thereby improving the performance of the application to a great extent. Consider a shopping cart application, which lists the products in the cart. The cart data can be sent to the client in the JSON format. Then, use templates to generate an HTML markup on the client side.

There are various types of client-side templating engines to choose from; some of them are logic-less such as Mustache and Handlebars, some are based on the HAML syntax such as Jade, and some others are based on John Resig's micro templating such as underscore.js.

In Kendo UI, a microtemplating library is used, which is called hash templates. In these templates, hash symbols are used to mark regions in the template that will be executed when the template is used to generate dynamic content.

How to do it…

The Kendo UI library exports an object, kendo, which is a namespace for various other objects and functions. The template function is one of them. The template function compiles hash-based templates into functions that can be evaluated for rendering. It is useful to render complicated bits of HTML from a JSON data source. The following are the three hash-based syntaxes:

  • The syntax to render literal values is #= #

  • The syntax to render HTML-encoded values is #: #

  • The syntax to execute arbitrary JavaScript code is # for(…) #

Let's take a look at a very simple example of rendering firstName and lastName of a person using the following hash-based template:

<script>
  
  var template = kendo.template("Full Name: " +"<span> #= lastName # </span>,"  +
    "<span> #= firstName # </span>");
  var data = {};
  
  data.lastName = "Smith";
  data.firstName = "Todd";
  
  var result = template(data);
  
  $('.addressContainer').append(result);
  
</script>

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Here, the #= <literal> # expression is used. Similarly, we can also use a hash-based expression to render HTML-encoded values:

<script>
  
  var template = kendo.template("Full Name: <span> # lastName # # </span>, <span> #: firstName # </span>");
  var data = {};
  
  data.lastName = "<b>Smith</b>";
  data.firstName = "<i>Todd</i>";
  
  var result = template(data);
  
  $('.addressContainer').append(result);
  
</script>

Here, the #: <literal> # expression is used. Rendering HTML-encoded values is particularly useful when you are accepting HTML strings as a part of a form input string, and they display the same in the result. The HTML characters\tags present in the data would be escaped and rendered as strings.

How it works…

Now, let's understand what is happening in the preceding code examples. In the first example, the first line is as follows:

var template = kendo.template("Full Name: " +
                              "<span> #= lastName # </span>,"  +
                              
                              "<span> #= firstName # </span>");

Here, the template function is used to compile the input string. Note that the input string contains HTML tags with hash-based expressions. This will return a function that can then be used with data to generate output. In the following four lines of the code snippet, a JavaScript data object with two variables, lastName and firstName, is created:

var data = {};

data.lastName = "Smith";
data.firstName = "Todd";

var result = template(data);

The last line in the preceding code snippet invokes the compiled function (assigned to the template variable), which then passes the JavaScript object as a parameter. This will replace the literal values inside the hash-based expression and generate the following output string:

Full Name: <span> Smith </span>, <span> Todd </span>

In the second example, the code is very similar, except that the #: <literal> # hash-based expression is used. This expression will escape the HTML tags and generate the output that contains HTML tags as it is.

There's more…

As seen in the previous examples, the HTML is passed as a string to the kendo.template function. An alternative to this is to define a template in a script tag:

<script type="text/x-kendo-template" id="testTemplate">

  # for (var i=0; i < functions.length; i++) { #
    <li> #= functions[i] # </li>
  # } #

</script>

Note the hash-based syntax used in the preceding code as well; it contains a JavaScript for statement that iterates over an array and generates list tags (<li> tags). Now, to compile this template, we will refer to the script tag using the id attribute:

<script>
  
  var templateContent = $('#testTemplate').html();
  
  var template = kendo.template(templateContent);
  
  var functions = ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"];
  
  var result = template(functions);
  
  $('.listContainer').append(result);
  
</script>

Here, the template is referred using the id attribute, #testTemplate. The content of the template is retrieved using $('#testTemplate').html(). The content is then used with the kendo.template function to generate the markup. This content is then inserted into the page by appending the same inside an unordered list using $('ul.listContainer').append(result).

Note

The script tag used here to write template has its type as text/x-kendo-template. This is a common way to implement templating on the client side. The browser simply ignores the script tag with a type that is not recognized by it.

 

Creating a two-way binding between View elements and JavaScript objects using the Model View ViewModel (MVVM) pattern


There are various architectural patterns that are used in most of the applications. The three very important architectural patterns are as follows:

  • Model View Controller (MVC)

  • Model View Presenter (MVP)

  • Model View ViewModel (MVVM)

These patterns are heavily used in structuring both the desktop and server-side applications. In recent years, these patterns have been applied to client-side applications as well. Frameworks such as AngularJS, BackboneJS, and EmberJS provide components that can be readily used to build applications that follow one of these patterns. All three patterns mentioned previously try to separate the development of the user interface from the development of the business logic.

The Model View ViewModel (MVVM) pattern is an architectural pattern, which is based on MVC and MVP. Here, the model layer represents the domain-specific data. An example application will include the bank account number, the holder's name, the balance amount, and so on. The model layer represents raw data that needs to be formatted to be consumed by View. The View layer consumes the data provided by the model and formats it as required. On the other hand, the behavior of the application or the business logic is encapsulated in a layer called ViewModel.

There are several frameworks, such as KnockoutJS, KnockbackJS, and Kendo UI, that implement the MVVM pattern. In Kendo UI, the MVVM pattern is at the core of the application framework. The framework provides APIs using which the various components, such as model, ViewModel, and data binding (that binds the markup to the ViewModel object) can be accomplished.

How to do it…

To illustrate how the MVVM pattern is implemented in Kendo UI, let's take a look at a very simple example in which the form elements are bound to a ViewModel object. The ViewModel object, in this case, would define the model data and also the behavior for one of the elements:

<form id="testView">
  
  Firstname: <input id="firstName" 
    type="text" 
    data-bind="value: fisrtName">
  <br/>
  
  Lastname: <input id="lastName" 
    type="text" 
    data-bind="value: lastName">
  <br/>
  
  Fullname: <input id="fullName" 
    type="text"
    data-bind="value: fullName"
    readonly>
  <br/>
  
  <input type="submit">
</form>

In the previous code snippet, a form with the id attribute, testview, that contains three input elements (textboxes) is created. Note the data-bind attribute in each one of these input elements. The data-bind attribute is used to specify the binding between View elements and the ViewModel object.

Here, the first input element specifies the value of the data-bind attribute as value: firstName. This indicates that the value of the input element is bound to the firstName model attribute. Now let's define ViewModel, which encapsulates the model data and behavior:

var viewModel = kendo.observable({
  fisrtName: "Sagar",
  lastName: "Ganatra",
  fullName: function() {
    return this.get("fisrtName") + 
           ' ' + this.get("lastName");
  }
});

A ViewModel object is created using the Observable interface on the kendo object. In this example, the ViewModel object contains the firstName, lastName, and fullName attributes. Note that while firstName and lastName are of the string type, the fullName attribute is a function that returns a string by concatenating firstName and lastName.

Now that we have the markup and ViewModel, they should be tied to each other. The bind method is used to bind View components to ViewModel:

kendo.bind($('form#testView'),viewModel);

The first argument to the bind function is the View component referred by using $('form#testView') and the second argument is the ViewModel object, viewModel. Once View and ViewModel are bound, any changes made to the model will update View, and any changes made by the user will be reflected in the model.

How it works...

When you execute the previously mentioned code snippets, the form elements with the values mentioned in the model are populated, as shown in the following screenshot:

Notice that in the markup, the last input element for FullName is read only. It is bound to a fullName model attribute, which is a function that returns the string concatenated by firstName and lastName. When you change the value of either firstName or lastName, the fullName model also gets updated and the same is reflected in the View class.

In the preceding screenshot, when the value of the Firstname input element is changed, the value of the Fullname attribute also gets updated. Note that the model attributes are updated on a blur event on the View component.

There's more…

In the previous screenshot, we saw how data binding can be used to set the values of input elements in the form. In addition to setting the value for some of the elements in the page, data binding can also be used to set attribute values (attr), to set HTML content (html), hide or show the elements in the page (visible and invisible), and so on.

Let's take a look at each one of these scenarios. The attr binding is used to bind tag attributes with model attributes in the following code snippet:

<a data-bind="attr: {href: websiteLink}"
  target="_blank">

  Click Here
  
</a>

In the preceding code snippet, the data-bind attribute has the attr: {href: websiteLink} value. Here, attr indicates that the tag attributes are bound to ViewModel. In this example, the href attribute of the anchor element is bound to a model attribute, websiteLink. The ViewModel object for the same would be as shown in the following code snippet:

<script>
  
  var viewModel = kendo.observable({
    websiteLink: 'http://www.packtpub.com',
  });
  
  kendo.bind($('a'),viewModel);
</script>

In the code snippet, the ViewModel object contains only one attribute, websiteLink. The value for this model attribute is an external link, which is http://www.packtpub.com. When the View component is bound to the ViewModel object, the anchor element is updated, which then has an attribute, href, that refers to the external link mentioned in ViewModel.

Similarly, the components in View can be hidden or shown on the page by using the binding attribute, visible :

<div id="view">
  <span id="container"
        data-bind="visible: isVisible">
    
          Some content here....
    
  </span>
  
  <br/>
  
  <button id="toggleVisible"
          data-bind="click: updateVisible">
    
    Toggle Visible
    
  </button>
</div>

In the previous code snippet, the span element has the data-bind attribute set to visible: isVisible. Here, the value of the isVisible model attribute should be of the Boolean type. If the same is false, then the style attribute of the span element is set to display: none. Also, the button has the data-bind attribute set to click: updateVisible. Here, the button's click event is bound to the model attribute, updateVisible. The ViewModel object for the previous markup is shown in the following code snippet:

var viewModel = kendo.observable({

  isVisible: true,

  updateVisible: function() {
  
    this.set('isVisible', !this.get('isVisible'));

  }
});

kendo.bind($('div#view'),viewModel);

The initial value for isVisible in ViewModel is set to true and hence the text, Some Content here…, (inside the span) would be visible. When you click on the toggleVisible button, it toggles the isVisible model attribute. This will either show or hide the span element.

 

Using Source and Template binding with ViewModels to generate HTML content


In the previous recipe, data binding between View components and ViewModel attributes was explored. Binding can be performed not only on the value of the form elements, but also on the attributes, and also to hide or show the elements on the page. In this recipe, we will look at the source and the HTML binding in combination.

Consider a dropdown (to select an element) that you want to populate it with data (option tags). The data for these could be provided from a ViewModel object; use a template to generate these option tags.

How to do it…

Let's first construct a ViewModel object:

var viewModel = kendo.observable({
    optionsData: [
                   {optionValue:1, optionName: "Test1"},
                   {optionValue:2, optionName: "Test2"},
                   {optionValue:3, optionName: "Test3"}
                 ]
});

The ViewModel object here contains an optionsData attribute, which is a collection (array) of objects. Each object in optionsData contains two attributes, namely optionValue and optionName. The optionValue attribute will be used for the value attribute of the option tag, and optionName will be used for the HTML content to be shown in the dropdown. The template that contains the option tag binding is shown in the following code snippet:

<script id="select-template" type="text/x-kendo-template">
  <option data-bind=
    "attr: {value: optionValue}, html: optionName">				
  </option>
</script>

Here, the template with the id attribute set to select-template contains one option tag. The option tag contains the data-bind attribute whose value is attr: {value: optionValue}, html: optionName. We already saw the attribute binding in action in the previous recipe. The other binding specified here is html. This binding is used to generate the HTML content for the tag. These option tags should be bound to the ViewModel object and be encapsulated inside a select tag.

The select tag can refer to the template (mentioned previously) and bind to the ViewModel object using the source attribute:

<select data-template="select-template" 
  data-bind="source: optionsData">
</select>

Here, the select tag specifies the two attributes, namely data-template and data-bind. The value of the data-template attribute is the id attribute of the template (the script tag) that we defined earlier, that is, select-template. This instructs kendo to bind the template to the select tag, and the generated content would become the HTML content for this select tag.

The data-bind attribute specifies a binding source that refers to the optionData model attribute in ViewModel. Now, the only step pending is to bind View elements to ViewModel, which is attained by executing the following line of code:

kendo.bind($('select'),viewModel);

How it works…

The select tag specifies the source binding that refers to the optionsData model attribute. This will make the collection of objects available to all the tags inside it.

The data-template attribute that refers to the template in the page is provided with the collection of objects (optionsData) and the template is iterated for the number of entries in the array. In this example, the optionsData collection contains three objects and hence, the template is generated three times and inserted as the HTML content for the select tag. The generated content would look like the following code snippet:

<select data-template="select-template" 
  data-bind="source: optionsData">
  
  <option data-bind=
    "attr: {value: optionValue}, html: optionName"  
    value="1">
    Test1
  </option>
  
  <option data-bind=
    "attr: {value: optionValue}, html: optionName"  
    value="2">
    Test2
  </option>
  
  <option data-bind=
    "attr: {value: optionValue}, html: optionName"  
    value="3">
    Test3
  </option>
  
</select>

The data- attributes would remain as they are, and the generated content now has the value attribute and the HTML content. Note that the preceding code could have been accomplished by using a for statement in a hash-based template and then appending the generated output to the select tag. However, using a data-template attribute and source binding allows you to do this seamlessly and write more intuitive code.

This pattern can be applied in various situations. Another example includes generating list tags (li elements) and inserting them into an unordered or ordered list.

 

Validating user input using the built-in Validator


Validating user-input data is one of the common tasks in any project. A client-side validation includes checking the form-input data for the type or for the missing data. This is not to say that the server-side validation is not important. However, a client-side validation takes care of performing basic validations and shows error or validation messages before submitting the form data to a server for processing. Therefore, it provides instant feedback to the user and improves the overall user experience.

With the advent of HTML5, the input fields in a form can have types defined for it. For example, an input field that should accept only an e-mail address can be specified as type=email. Similarly, the input fields can have types such as URL, NUMBER, RANGE, DATE, SEARCH, and COLOR. When the user specifies incorrect data for any of these fields, the browser will show an appropriate validation message. In addition to the types, the form elements can also be marked as required by adding an additional attribute, required, to the input elements. However, some of the old browsers don't support HTML5 features, including the previously mentioned form validation. The Kendo UI library comes with a built-in validator that can be used to perform client-side validations.

The Kendo UI validator encourages users to use HTML5-like syntax and provides out-of-the-box support to make the form validation work on older browsers.

How to do it…

Let's take a look at an example where in one input, the text field is marked as required, and the other input field of the email type is also marked as required. Please note that this is very much an HTML5 syntax and the user doesn't have to alter the markup to mark the fields as required or of a different type:

<form id="testView">
  
  <label for="firstName">First Name</label>
  <input id="firstName"
    name="First Name"
    type="text" 
    required
    validationMessage="Please specify First Name">

  <br>

  <label for="emailId">Email Address</label>
  <input id="emailId"
    name="Email Address"
    type="email" 
    required
    data-required-msg="Please specify Email Address"
    data-email-msg="Email format is not correct">
  <br>

  <input type="submit">
</form>

In the preceding markup, the input fields are marked as required and validation messages are defined in data- attributes. After specifying the validation messages in the markup, the last step is to attach the kendo validator to the form. This is attained by executing the following code snippet:

$("form#testView").kendoValidator();

In the previous code snippet, the form element is marked for validation by calling the kendoValidator function on the same.

How it works…

In the previous markup, the firstName field is of the text type and is marked as required by adding the required attribute. Also, a validationMessage attribute that specifies the validation message to show when the user doesn't provide any input data is mentioned. The next input element, emailId, is of the email type and is marked as required as well. In this case, there are two rules that are applicable; firstly, the field is required, and secondly, the user should enter a valid e-mail address. Therefore, we need to specify two validation messages for the input field. Here, the data-required-msg and data-email-msg attributes are specified. When the user doesn't specify any value, the validation message specified in data-required-msg is displayed. Also, when the user specifies an invalid e-mail address, the validation message specified in data-email-msg is displayed.

Now, let's see this in action; when the user doesn't specify values for both the fields, then the required validation message would be shown as follows:

When the user clicks on the Submit button, the validator runs, inspects the input data, and shows the validation message if there is no data specified. Now, when the user keys in an invalid value in the e-mail field, the validation message specified in data-email-msg would be shown as follows:

Here, both the fields have some data in place and hence, the required field validation has passed. However, the e-mail address is not valid and, hence, you see the corresponding validation message being shown.

Note

By default, the field is validated when it loses focus. This is called the onBlur event. This can be disabled by passing the validateOnBlur: false option to the kendoValidator method:

 $("form#testView").kendoValidator({
  validateOnBlur: false
 });

There's more…

In the previous example, we saw that the validation message was specified in the markup. It is also possible to configure the validator so that the same message is applicable to all fields with a specific validation rule. For example, all required fields can have the same validation message, such as This field is required.

The messages configuration option can be used to set the various validation messages that can be applied across all the input elements, as shown in the following code snippet:

$("form#testView").kendoValidator({
    messages: {
    // {0} would be replaced with the input element's name
    required: '{0} is required'
    
    email: 'Enter a valid email address'
  }
});

Here, the validation messages are removed from the markup and the same is specified in the kendoValidator method. Note the use of {0} in the validation message for the required fields. Here {0} is replaced with the input element's name. For example, if the first name is not specified, the message would be First Name is required.

Similarly, in the case of fields of the email type, the Enter a valid email address validation message is shown if the user doesn't provide a valid e-mail address.

In a case where the validation message is specified in the markup as well as in the kendoValidator method as options, the message specified in the markup would take precedence.

It is also possible to define custom validation rules in addition to the standard set of validation rules mentioned previously. This is done by passing the rules option to the kendoValidator method. Let's consider the same example form that contains two input fields, namely firstName and emailId.

Now, let's add a custom rule that doesn't allow numbers to be entered in these fields:

$("form#testView").kendoValidator({
  
  rules: {
    customRule1: function(input) {
      var re = /^[A-Za-z]+$/;
      return re.test(input.val());
    }
  },
  messages: {
    customRule1: 'Numbers are not allowed'
  }
});

In the preceding code snippet, a custom rule, customRule1, is defined. When the form is being validated, all input fields are checked against this custom rule. Here, a regular expression is used to test whether the value of the input element contains a numeric value. If this returns false, then the validation message (defined under the messages object) Numbers are not allowed is displayed.

As highlighted in the preceding screenshot, the validation message is shown as the user has entered alphanumeric characters.

About the Author

  • Sagar Ganatra

    Sagar Ganatra is a frontend engineer and an architect from Bangalore, India. He has more than a decade of experience in developing web and mobile applications. He specializes in architecting projects using JavaScript and frameworks such as React, Angular, and Node. His previous books include Kendo UI Cookbook and Instant Kendo UI Mobile, both published by Packt Publishing. He also writes about frontend technologies in his blog, sagarganatra (dot) com.

    Browse publications by this author
Book Title
Access this book and the full library for just $5/m.
Access now