Quantcast
Channel: Kendo UI – Falafel Software Blog
Viewing all 43 articles
Browse latest View live

Creating a SPA using Telerik Kendo UI

$
0
0

As the SPA concept and the modern web technology behind it have grown, so have the available frameworks to support its development. A SPA is a great way to create a smooth client experience similar to an phone or desktop application – especially for lightweight and interactive websites who need very little compatibility with older browsers.

While there are plenty of great SPA supporting javascript frameworks available, I will cover how to get the Kendo SPA framework up and running inside an MVC.NET project.

Setting up server-side

Let’s cover the various MVC5 components and how we will use them to delegate control to the SPA. There are quite a few ways you can handle this step but I will cover the one that is likely going to be the simplest.

Step 1: Create a base MVC controller with a default action that is responsible for loading the initial data or your SPA as well as rendering the View that houses your spa template.

Step 2: Create your controllers and actions for the pages of your SPA. This is necessary if your SPA is still url-driven. A lot of SPA applications don’t care to maintain page urls in their app but if you do you can still use basic MVC actions to control any page-entry specific logic as well as return the SPA template. The client router won’t call these actions but they will server as an entry point for the app at that URL.

At this point your MVC controllers should be returning the View that will be responsible for housing the SPA template.

Setting up client-side

Now you are returning a view which is likely just a basic HTML page with kendo loaded to it. From here you will need to configure the necessary components for your SPA.

Step 1: Set up the router

The router is responsible for your page routing locally. It understands the client state of your SPA and is used to facilitate client side navigation.

var router = new kendo.Router({
    pushState: true, //use HTML pushstate instead of hashbangs
    routeMissing: function(e){
        //think of this like a local 404
    },
    change: function(e){
        //fires any time the route changes
    }
});

Step 2: Create the layout

We will need to create a layout that acts similar to a master view for our individual views in the next step. We could do this with a template or just as simply as the example here.

var layout = new kendo.Layout("<div id='view-wrapper'></div>");

Step 3: Create your first view

A kendo view is more than just a “page” it can be used in multiple ways, however, for this basic example it will be treated as if it is a “page” of the SPA. The markup for the view goes inside a script tag with the x-kendo-template type, a kendo template.

<script id="home-page" type="text/x-kendo-template">
    <div data-bind="text: content"></div>
</script>

The ID if the template is the first parameter in the javascript used to wire up your view.

var home = new kendo.View("home-page", 
{
    init: function(e){},//When the view is initialized
    show: function(e){},//When the view is presented
    hide: function(e){},//When the view is being moved away from
    model: new kendo.observable({
               content: "This is the home page"
           })
});

In the view you see we set up the model as a kendo observable and defined an object called “content” that holds some text. In the mark up in the template above we bind the text of the div to this value.

There are a few other useful configurations you can make to the kendo view and I would suggest reading over the documentation here.

Step 4: Define the route

Now that we have our router set up and a basic view configured we need to configure the route. The route itself tells the router that we need to match our view with a specific url. Here we are binding the root url “/”.

//Home Page : /
router.route("/", function(){
    layout.showIn("#view-wrapper", home);
});

Now that we have our route configured we need a way to navigate to it. The base of navigation is done via router.navigate();

router.navigate("/")

Tips and Tricks:

  • When adding more views make sure that there is a server-side controller that matches the URL of your kendo route or that your server is aware that all urls might be valid and to return a default view regardless. The router won’t contact the server but if you want additional urls to act as entry points into the app then the server needs to know these urls exist.
  • You can use jQuery to override the default click event for the anchor tag. This useful if you want to keep urls on your page for both inside the spa and external without the internal links reloading the app. In the example below all internal links are tagged with a data-internal=’true’ attribute.
$("body").delegate("a", "click", function(e){
    var href = $(this).attr("href");
    var internal = $(this).data("internal");
    if(internal == "true" || internal == true){
        router.navigate(href);
        return false;
    }
});

 

 

 

The post Creating a SPA using Telerik Kendo UI appeared first on Falafel Software Blog.


Manipulating a kendo view on show

$
0
0

When calling a kendo view there is a timing issue related to interacting with or manipulating a data-bound control and its child items in the DOM. In my case I needed to automatically scroll to the bottom of a MVVM template/source bound table each time the view was loaded – not the kendo grid control. The problem stemmed from a couple core issues:

  1. Most browsers will not properly determine the scrollHeight property of a hidden element.
  2. Kendo seems to render in the DOM the view (from the template) it is going to show but keeps i t’display:none’, even during the ‘show’ event while at the same time the view we are leaving is also still in the DOM but is visible.
  3. There is no  ‘view ready’ type event that fires after the current view is fully displayed in the DOM. As mentioned above the ‘show’ event and other events such as ‘transitionStart’ and ‘transitionEnd’ are executed with the view still hidden in the DOM.

The result in my case was that on initial load the scrollToBottom method would fire successfully since there was no transition of views going on (therefore the view showing was never hidden in the DOM). But on any subsequent visits to any page using that view it didn’t work.

My solution was to create a custom kendo widget that would be simple and lightweight and simple like the template/source MVVM bindings yet was aware of its datasource state and exposed events such as dataBound and dataBinding that I could hook into to see exactly when the elements were being rendered in their parent container.

var Repeater = kendo.ui.Widget.extend({
            init: function (element, options) {

                var that = this;

                kendo.ui.Widget.fn.init.call(that, element, options);
                that.template = kendo.template(that.options.template || $("#table-tmp").html());

                that._dataSource();
                that.trigger("dataBound");
                
                //just sets the element to the same height as its parent 
                var toheight = $(this.element).parent().height();
                $(this.element).height(toheight);
            },
            options: {
                name: "Repeater",
                autoBind: true,
                template: ""
            },
            refresh: function () {
                var that = this,
                    view = that.dataSource.view(),
                    html = kendo.render(that.template, view);
                that.trigger("dataBinding");
                //this is where the UI is built
                that.element.html(html);
                that.trigger("dataBound");
            },
            _dataSource: function () {

                var that = this;

                if (that.dataSource && that._refreshHandler) {
                    that.dataSource.unbind("change", that._refreshHandler);
                }
                else {
                    that._refreshHandler = $.proxy(that.refresh, that);
                }

                that.dataSource = kendo.data.DataSource.create(that.options.dataSource);
                that.dataSource.bind("change", that._refreshHandler);

                if (that.options.autoBind) {
                    that.dataSource.fetch();
                }
            },
            events: ["dataBinding", "dataBound"],
            items: function () {
                return this.element.children();
            },
            setDataSource: function (dataSource) {
                this.options.dataSource = dataSource;
                this._dataSource();
            }
});
//register the widget
kendo.ui.plugin(Repeater);

I could then use MVVM to still bind my new widget.

<table id="repeater" class="tableSection">
            <thead></thead>
            <tbody data-role="repeater" data-bind="source: Items, events: { dataBound: scrollBottom } "></tbody>
</table>

I listen to the ‘dataBound’ event which fires after the data items have been injected into the DOM as you can see above in the ‘refresh’ section of the custom widget. It was important to listen here because when a transition between views of the same type was being made the aforementioned events (show, etc) were executing while the DOM contains the markup for BOTH views. This occurs even if you are reusing the same view model. Kendo will generate the markup for the new view and inject it into the DOM before destroying the old one. This is a pain because you now have duplicated IDs on the page during the view’s show events and you cannot target elements via ID accurately at this point. The ‘dataBound’ event exposes the element making the request which is the one transitioning into view. We can also target the view-wrapper which kendo is keeping hidden and show it to get an accurate scrollHeight. Since the very next action that fires in the rendering of a view is to show this element anyways, it doesn’t break any animations or cause any undesired effects.

//...View definition...
model: kendo.observable(
                {
                    Items: [],
                    scrollBottom: function (e) {
                        //forces the view wrapper parent to visible so we can get an accurate scrollHeight
                        $(".view-wrp").parent().show();
                        var d = $(e.sender.element);
                        d.scrollTop(d.prop("scrollHeight"));
                    }
                })

With these changes I was able to effectively manipulate my table while the view was being shown without implementing any hacky timers.

 

 

The post Manipulating a kendo view on show appeared first on Falafel Software Blog.

Kendo UI SPA and Require.js

$
0
0

As you build a Kendo UI single-page app, one of the first decisions you will have to make is how you want to organize your code. Unlike some other SPA frameworks, for example Durandal, Kendo’s SPA implementation doesn’t do much to dictate your code layout.

One approach I like to take is to use Require.js to separate my views and view models into their own files. This helps to keep proper separation of views and their logic, and also sets up dependency injection.

One nice feature of the Durandal SPA framework is that it supports this concept out-of-the-box by using Require.js and its Text plugin to load views and view models remotely.

Inspired by this concept, I built a kendo-template plugin for Require.js that can be used to load SPA views from separate HTML files.

Structuring a SPA using the kendo-template plugin.

Let’s take a look at one possible way to structure your application, using Require.js and the kendo-template plugin.

Since we will have multiple views in our SPA, let’s made a “views/” directory for them to be in. Furthermore, each view can optionally be placed in its own directory.

First we can define our view HTML. As an example, let’s make a SPA that is just a basic “Hello World” application. To better organize our files for development, let’s put this in its own directory. A possible name would be: “views/hello/helloView.html”

<!-- views/hello/helloView.html -->

<div>
    <span data-bind="message"></span>
</div>

Now we will want to define a Kendo SPA kendo.View instance. We can do this in a file named: “views/hello/helloView.js”

// views/hello/helloView.js

require(["kendo", "kendo-template!views/hello/helloView"], function (kendo, viewTemplate) {
    "use strict";

    var viewModel = kendo.observable({
        message: "Hello World!"
    });

    return new kendo.View(viewTemplate, {
        model: viewModel
    });
});

This is where the Require.js kendo-template plugin comes in. The plugin will use the Require.js Text plugin to load the “helloView.html” files, then use jQuery to turn the string into DOM elements, and finally append it to the document body. The plugin then returns the string id of the element that contains the template into the “viewTemplate” variable. The first parameter to the “kendo.View()” constructor is the ID of the element to use as the template, so the “viewTemplate” variable is passed in here.

Now the “helloView” SPA view instance can be added to the router. Since we may need to render multiple “kendo.View” instances into a Layout (for example, we may need to also render a “Navbar” view along with our “Hello” view) it is a good idea to make a “Route” file as a separate JavaScript file.

// routes/hello.js

define(["views/hello/helloView"], function (helloView) {
    "use strict";

    // called when this route is navigated to.
    function show() {
        helloView.render("#mainContent");
        // also render any other views, for example a NavBar or ToolBar
    }

    return function (router) {
        router.route("/", show);
        router.route("/hello", show);
    };
});

Finally, when our application is initialized, we can gather up all our “routes” and register them with the Kendo UI SPA Router, and start our application.

// main.js

require(["kendo", "routes/hello"], function (kendo, helloRoute) {
    "use strict";

    var router = new kendo.Router();

    helloRoute(router);
    // also add any other routes...

    router.start();
});

And there we have it! Now our code has a nice, maintainable layout:

main.js

routes/
    hello.js

views/
    hello/
        helloView.html
        helloView.js

One of the nice things about using the kendo-template plugin is that it allows us to keep our view HTML and JavaScript together in the same directory, instead of putting the HTML for every view into one big unwieldy index.html file.

Optimization

When using Require.js, you should always consider using the r.js optimizer before sending your code to production. This will combine all your required dependencies into a single file, making the client browser load faster.

When the kendo-template plugin optimizes the view templates, it will result in code that looks like:

define("home-homeView-template", [], function () {
    $('<script id="home-homeView-template" type="text/x-kendo-template">...</script>')
    .appendTo("body");
});

When the browser runs the optimized JavaScript, it will append all the templates to the page at that time.

The post Kendo UI SPA and Require.js appeared first on Falafel Software Blog.

Kendo Grid Hierarchy with Shared Column Headers

$
0
0

The Kendo Grid is one of the most complex and configurable widgets in the Kendo framework.  One of the options is to use a hierarchical grid which allows you to display data in a master/detail or parent/child configuration.  The default layout will give you an expand/collapse button with a child grid that has its own columns and headers, as displayed in the Hierarchy Grid Demo:

Hierarchical Kendo UI Grid _ Kendo UI Web

But what if your parent and child grids have the same columns and you want to show the child columns in line with the parent row?  Fortunately, we can do this with a little JavaScript and CSS.

Step 1: Same Number of Columns

The first step is to ensure that your parent and child grids have the same number of columns.  This doesn’t require anything special if the data object is exactly the same, but sometimes you won’t have certain columns in the child object that exist in the parent object or vice versa.  To keep the columns aligned, we need to specify the columns explicitly and specify an empty column to leave space when there is no data at that level.  In this example, I simply set the column template to a space as an empty placeholder:

<div id="grid"
        data-role="grid"
        data-bind="source: parentChildData"
        data-detail-template="tmpl-child-detail"        
        data-columns="[
            { field: 'name' },
            { field: 'address' },
            { template: '&nbsp;', title: 'grade' }
        ]"></div>
    
    <script id="tmpl-child-detail" type="text/x-kendo-template">
        <div data-role="grid"
             data-bind="source: children"
             data-columns="[
                { field: 'name' },
                { template: '&nbsp;' },
                { field: 'grade' }
             ]"></div>

    </script>

 

Step 2: Hide Child Grid Headers

Now that our columns are aligned, we no longer need the default column headers in the child grid.  We can hide them with some simple CSS (scope this rule further, as needed):

.k-grid .k-detail-cell .k-grid-header {
  display: none;
}

Depending on the theme you are using, you may need to do a few more CSS tweaks to add or remove padding around the child grid.  See my full code below to see some of the other CSS rules that I applied.

Step 3: Set Column Widths

This isn’t always necessary, but if you find that your columns are not aligned after the first two steps above, you may need to programmatically set the column widths in the child grid.  Typically, this will be needed if you have content that exceeds the width of the evenly-spaced columns. The JavaScript snippet below should be called on the detailInit event of the grid and also any time the window is resized.  This will select all detail rows and set the width of each column to match the width of the corresponding column in the k-master-row above.  You’ll notice that it is using nth-child() to skip over the hierarchy cell that precedes all of the content cells.

function resizeDetailGrid(gridElement) {
        // resize detail column widths to match master column headings
        gridElement.find('.k-detail-cell tbody tr td').each(function (index) {
            var headerCell, detailCell, headerCellSelector, detailCellSelector;
            headerCellSelector = kendo.format('.k-master-row td:nth-child({0})', index + 2);
            detailCellSelector = kendo.format('.k-detail-cell tbody tr td:nth-child({0})', index + 1);
            headerCell = gridElement.find(headerCellSelector).first();
            detailCell = gridElement.find(detailCellSelector);
            detailCell.width(headerCell.width());
        });
    }

Now you have a grid that will look like this (feel free to edit the CSS to make it a bit more colorful!):

Kendo Parent Child Grid - JSFiddle

See the full code in this JSFiddle.

 

The post Kendo Grid Hierarchy with Shared Column Headers appeared first on Falafel Software Blog.

Kendo UI: Displaying a Custom Message when Grid is Empty

$
0
0

By default the Kendo UI Grid doesn’t provide the user with any feedback when the grid is empty.   The grid just displays the column headers.

DefaultEmptyGrid

When paging is enabled things get a little better but this isn’t ideal.  First, it requires paging to be enabled which isn’t always the case.  Secondly the message is tucked away in the lower right hand corner and isn’t very prominent.

EmptyGridWithPaging

Ideally, something like this does a much better job of providing the user with feedback:

EmptyGridWithCustomMessage

Luckily making this happen is really straight forward.  Start by creating a function that will be called on DataBound of the grid.  At this point in the grid’s lifecycle it has completed the databinding process and it is safe to check the record count.  Once it is determined that there are not any records an empty row can be appended to the table body of the grid displaying the custom message.  Finally, configure the grid to use the new function.

function gridDataBound(e) {
    var grid = e.sender;
    if (grid.dataSource.total() == 0) {
        var colCount = grid.columns.length;
        $(e.sender.wrapper)
            .find('tbody')
            .append('<tr class="kendo-data-row"><td colspan="' + colCount + '" class="no-data">Sorry, no data :(</td></tr>');
    }
};

function initializeGrid(data) {
    $("#people").kendoGrid({
        dataSource: {
            data: data
        },
        columns: [
            {field: "Title", width: "50px"},
            {field: "FirstName", title: "First", width: "100px"},
            {field: "LastName", title: "Last", width: "100px"},
            {field: "Occupation", width: "150px"}
        ],
        scrollable: false,
        dataBound: gridDataBound
    })
};

If the grid does have paging enabled and you don’t want to display the default Kendo UI message and the new custom message you can add the line of code below to the DataBound handler to clear out the default message.

e.sender.pager.options.messages.empty = ""

You end up with a more informative message when the Kendo UI grid doesn’t contain any data.

FinalGrid

The post Kendo UI: Displaying a Custom Message when Grid is Empty appeared first on Falafel Software Blog.

Connect KendoUI AutoComplete to MVC Action

$
0
0

The Kendo UI AutoComplete widget supports server-side filtering by default, but normally it expects to work with an OData datasource.  If you’re not using Web API and just want to use a simple MVC controller action as the server call for the AutoComplete, this can present a challenge.  By default, the AutoComplete data source is going to send a complex filter object as part of the querystring, like this:

?filter%5Blogic%5D=and
&filter%5Bfilters%5D%5B0%5D%5Bvalue%5D=2
&filter%5Bfilters%5D%5B0%5D%5Boperator%5D=contains
&filter%5Bfilters%5D%5B0%5D%5Bfield%5D=OrderNumber
&filter%5Bfilters%5D%5B0%5D%5BignoreCase%5D=true

You can make some sense of this if you run it through the JavaScript decodeURIComponent function:

decodeURIComponent("filter%5Blogic%5D=and&
filter%5Bfilters%5D%5B0%5D%5Bvalue%5D=2
&filter%5Bfilters%5D%5B0%5D%5Boperator%5D=contains
&filter%5Bfilters%5D%5B0%5D%5Bfield%5D=OrderNumber
&filter%5Bfilters%5D%5B0%5D%5BignoreCase%5D=true")

//returns
"filter[logic]=and
&filter[filters][0][value]=2
&filter[filters][0][operator]=contains
&filter[filters][0][field]=OrderNumber
&filter[filters][0][ignoreCase]=true"

Now at this point, you can use the built-in MVC model binding to make this work by creating a C# object that has the same structure as the filter object being passed, and then making your action accept this type as its parameter. However, in the case of a simple widget like AutoComplete, OData and complex filtering is overkill.  The only thing that is going to change from one request to the next is the value (in this case 2) that we’re filtering on.  We’re not going to change the logic, the operator, the field, or whether or not we ignore case in midstream as the user is typing characters into a textbox.  So what we really would like is for our MVC action to simply accept a filter string that contains the value we want to filter on, and then we can perform our server-side filtering accordingly.

So, how can we replace the OData that the Kendo UI datasource generates by default with a much simpler querystring that MVC can easily work with?  The parameterMap function within the dataSource property is the key.  It accepts two parameters, data and action.  The data parameter is the object that will be sent to the server and the action is the datasource action (read, update, etc.).  In the case of an AutoComplete widget, we will only use the read action, so we can ignore this parameter.  The return value of parameterMap is the new object that will be sent.  We want this to be as simple as possible, so we will return an object with a single property and associated value.

$("#autocomplete").kendoAutoComplete({
    dataSource: {
        serverFiltering: true,
        transport: {
            read: {
                url: "http://localhost/Orders/List"
            },
            parameterMap: function (data, action) {
                var newParams = {
                    filter: data.filter.filters[0].value
                };
                return newParams;
            }
        }
    },
    pageSize: 5,
    filter: "contains",
    dataTextField: "OrderNumber"
});

Now when we look at the call being made to the server, the querystring is simply:

?filter=3

Which we can easily configure our MVC action to support:

public ActionResult List(string filter)
{
// implement filtering
}

Summary

OData provides powerful, standard mechanisms for filtering data via HTTP requests. However, it can be overkill in many scenarios, and in particular if you are not using WebAPI in your ASP.NET application, it can be much simpler to implement filtering using a single querystring value. Using the parameterMap function, you can control how the Kendo UI datasource communicates with your server-side methods.  Thanks to Jeff Valore for his assistance with this implementation.

The post Connect KendoUI AutoComplete to MVC Action appeared first on Falafel Software Blog.

Check for duplicate items in Kendo UI ListView before adding the item from Kendo UI AutoComplete

$
0
0

In one of the projects I’m working on, I had a requirement to do the following tasks:

  1. Show a list of items in Kendo UI AutoComplete. It will fetch JSON data from the ASP.NET MVC Action.
  2. Add selected item(s) from Kendo UI AutoComplete to the Kendo UI ListView, while checking if the item already existed in the list. If it does not exist, add the item calling ASP.NET MVC Action or else take no action.
  3. Refresh the data source of Kendo UI ListView locally.

In this post I will show you how to complete the above tasks. First, let us have a look at the ASP.NET MVC Action which returns data in the JSON format as shown below:

public JsonResult GetAllAccounts()
        {
            var result = _accountRepository.List();
            return Json(result, JsonRequestBehavior.AllowGet);
        }

The Kendo UI AutoComplete widget fetches data from the GetAllAccounts action as given below:

var getAllAccountsUrl = "/Accounts/ GetAllAccounts ";
            $("#accountAutoComplete").kendoAutoComplete({
                placeholder: "Select account",
                minLength: 3,
                filter: 'contains',
                dataTextField: "account",
                dataValueField: "Id",
                dataSource: {
                    transport: {
                        read: {
                            url: getAllAccountsUrl,
                        }
                    }
                }
            });

In the mark up of cshtml you need to define an element with id accountAutoComplete.

<input id=" accountAutoComplete "  /> 
<button type="button" id="addaccountbutton">Add Account</button>

Button is converted to a KendoUI Button using the following script:

$("#addaccountbutton").kendoButton({
                icon: "plus",
                click: addAccounttoUser
            });

Next, upon clicking the button, we have to perform the following tasks:

  1. Check that the item exist in the Kendo UI ListView.
  2. If it does not exist, then call the ASP.NET MVC Action to add the item.
function addAccounttoUser(e) {
               
                var accounttoadd = $("#addaccounts").data("kendoAutoComplete").value();
                var dataFromList = dataSource.data();
                var flag = true;
                for (item in dataFromList) {
                    if (dataFromList[item].accountname == accounttoadd) {
                      flag = false;
                       break;
                  }

                
                }
                if (flag) {

                    $.ajax({

                        // the url to the service
                        url: "/Users/AddAccount?UserId=" + id + "&AccountName=" + accounttoadd,

                        // the format that the data should be in when
                        // it is returned
                        contentType: "json",

                        // the function that executes when the server
                        // responds to this ajax request successfully
                        success: function (data) {

                            console.log("data added succesfuly");                            
                            dataSource.read();
                        }

                    });

                    
                }


                $("#addaccounts").data("kendoAutoComplete").value("");

In the above code snippet, we are checking the loop for whether the selected item already exists in the ListView datasource or not
duplicateitemimg1
If the item does not exist in the datasorce, then the flag will be true. Check that the flag value and condition inside it are calling the MVC action to add the item. Once the item is successfully added, the success function will be called in $.ajax(). In the success function call, read the function in the datasource to refresh KendoUI ListView.
duplicateitemimg2

We have now created a Kendo UI ListView as shown below:

var listView = $("#accountslstview").kendoListView({
                dataSource: dataSource,
                template: kendo.template($("#template").html())
            }).data("kendoListView");;

And the datasource is created as below:

var dataSource = new kendo.data.DataSource({
                transport: {
                    read:
                    {
                        url: getexistedAccountsUrl,
                        contentType: 'application/json; charset=utf-8',

                    },
                    
                    parameterMap: function(options, operation) {
                        if (operation !== "destroy" && options.models) {
                            return { models: kendo.stringify(options.models) };
                        }

                    }
                },
                schema: {
                    model: {
                        id: "Id",
                        fields: {
                            Id: { editable: false, nullable: true },
                            accountname: { type: "string" }

                        }
                    }
                }

            });

Kendo UI ListView is the created with a template as follows:

<div id=" accountslstview " style="margin-top:30px"></div>
            
            <script type="text/x-kendo-tmpl" id="template">
                <div>
               
                    
                        #:accountname#
                        
                    
                </div>
            </script>
        </div>
    </div>

Following these steps, you can fetch data from the ASP.NET MVC action in Kendo UI AutoComplete. Select an item from the AutoComplete widget and check for duplicity in KendoUI ListView before adding it.

Hope it helps. Happy Coding.

The post Check for duplicate items in Kendo UI ListView before adding the item from Kendo UI AutoComplete appeared first on Falafel Software Blog.

Use Twitter Bootstrap grid layout inside a Kendo widget

$
0
0

Twitter Bootstrap is a fine foundation to build your website on, and it is easy to put Kendo widgets into a Bootstrap grid layout. But what if you want to use Bootstrap grid layouts within a Kendo widget? Out of the box, it will not work! Here is an example inspired by a page layout I was challenged to create recently. The entire page is contained in a Kendo TabStrip, and then each tab’s body is laid out with a Bootstrap grid. Now, if you have no need for the rich programming model of the Kendo TabStrip, the trivial solution is simply to use a Bootstrap .nav.nav-tabs instead. Let’s proceed as if there is a good reason to prefer using the Kendo TabStrip. Here’s an example JSBin illustrating the problem you will notice immediately:
kendo-bootstrap-grid-1
Somehow the sizing of the grid has gone seriously awry! A full 50% of the columns have wrapped to the next line! But fear not, for the solution is really quite simple if you know what to look for. You see, Bootstrap is built from the ground up on the foundation of border-box box sizing, but Kendo overrides this and sets the box-sizing of its children to content-box. Kendo’s rule, while it does break Bootstrap layouts, can nevertheless be seen as a sensible one because content-box is the default box sizing as defined by the CSS standard. Border-box sizing is easier to reason about and program for, but is not the default.

Once you understand this, the fix is obvious: restore border-box sizing within Kendo widgets, but only on an as-needed basis. Changing it everywhere will probably wreak havoc with how Kendo renders its own widgets, so you want to use a light touch. Here’s the rule that changes the box-sizing to content-box:

.k-animation-container, .k-widget, .k-widget *, .k-animation-container *, .k-widget *:before, .k-animation-container *:after, .k-block .k-header, .k-list-container {
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
}

It’s the “.k-widget *” selector that’s responsible for this. The selector means “All child elements of .k-widget elements.” To override this, you need a selector that’s at least as specific but can be selectively applied. For this purpose, I suggest a rule like the following:

.k-widget .border-box-sizing,
.k-widget .border-box-sizing * {
    box-sizing: border-box;
}

Then, simply include this .border-box-sizing class along with the Bootstrap container class, and the grid layout works again!
kendo-bootstrap-grid-2

The post Use Twitter Bootstrap grid layout inside a Kendo widget appeared first on Falafel Software Blog.


Using the AngularJS $http Service inside a Kendo UI DataSource

$
0
0

Kendo UI is a widget library full of great UI widgets, but its also an application framework for developing JavaScript applications. AngularJS is another application framework for JavaScript, but it lacks any UI components. Increasingly, developers are leaning on AngularJS as their primary front-end framework, but because of it’s lack of UI components, these developers must look elsewhere for help building their user interfaces.

Never fear, though, because Kendo UI doesn’t force you to use its application framework to be able to use its UI widgets. In fact, Telerik recently added AngualarJS directives to the product to make sure it integrates well with AngularJS applications. Out of the box, things work quite seamlessly together between these two libraries, but there are a few tricks that make things work even better.

One of those tricks is based on the difference in how each framework accesses data services. Kendo uses JQuery’s ajax method to access HTTP services. Angular uses its $http service object. This can cause a couple of different problems for a developer:

  1. It can make it more difficult to reuse your AngularJS code in the form of services and factories. Normally you’d want your controllers to get data from a service and give it to the UI. Bu, when you’re accessing the data for a Kendo Widget, it has to be through the Kendo DataSource object.
  2. It can be difficult to use the mocking features of AngularJS to test Kendo widgets because they will circumvent the mocked $http service, instead using JQuery.ajax() to access their data.

The solution to both of these problems is actually fairly simple. You can wrap your AngularJS services inside of the Kendo UI DataSource. The DataSource allows you to overload its read, create, update, and destroy actions with custom JavaScript methods. Then, any time a Kendo widget needs data, it will execute your custom function inside it’s DataSource which will use the $http service internally. Here’s a JSFiddle that demonstrates how this works:

NOTE: The above code example is simplified for readability. As I mentioned, you’ll actually want to wrap a service of your own (which in turn will use the $http service internally) inside the Kendo UI DataSource.

I hope that’s useful on your Kendo-Angular projects like it is on mine!

The post Using the AngularJS $http Service inside a Kendo UI DataSource appeared first on Falafel Software Blog.

Kendo Editor with a Disabled Binding in MVVM

$
0
0

Have you ever used the Disabled binding on Kendo widgets with MVVM? It is really helpful to restrict the user’s editing, either based upon their current selections or based upon some login or role options. According to the documentation, we can use the Disabled binding for input, select, and textarea elements. But what about the Kendo Editor? It’s basically a big combination of a bunch of smaller elements, right?

With just a little work, we can set up a custom binding to allow Disabled to work for the Editor as well. But not only do we want it to actually be disabled (as in, the user can’t input any text), but we want it to look disabled too, so the user doesn’t think there is just something wrong with the text portion.

To begin with, just take a look at some regular inputs and the Editor, in enabled mode. I’ve added a checkbox to allow us to bind the Enabled/Disabled state of the editors all together:

2014-12-28 12_09_09-Kendo Disable Widget Examples - JSFiddle

 

And now, the custom binding for the Kendo Editor:

kendo.data.binders.widget.editorDisabled = kendo.data.Binder.extend({
            init: function (element, bindings, options) {
                kendo.data.Binder.fn.init.call(this, element, bindings, options);
            },

            refresh: function () {
                var enable = !this.bindings.editorDisabled.get();

                //selectboxes
                $('[data-role=selectbox]', this.element.toolbar.element)
                    .getKendoSelectBox()
                    .enable(enable);

                //comboboxes
                $('[data-role=combobox]', this.element.toolbar.element).each(function () {
                    $(this).getKendoComboBox().enable(enable);
                });

                //pickers
                $('[data-role=colorpicker]', this.element.toolbar.element).each(function () {
                    $(this).getKendoColorPicker().enable(enable);
                });

                //buttons
                $('.k-tool-icon', this.element.toolbar.element).toggleClass('k-state-disabled', !enable);

                //text area
                $(this.element.body).attr('contenteditable', enable);
                $(this.element.body).css('visibility', enable ? 'visible' : 'hidden');
            }
        });

Now, we can just use data-bind to bind our new editorDisabled to the checkbox property, and the Editor acts and looks disabled:

2014-12-28 12_09_48-Kendo Disable Widget Examples - JSFiddle

 

You see the entire example here:

Hope you find it useful!

The post Kendo Editor with a Disabled Binding in MVVM appeared first on Falafel Software Blog.

Stop Kendo Template Capitalization Mishaps in Visual Studio 2014 Copy/Paste

$
0
0

If you have ever used Copy/Paste to move a Kendo template to a new file in Visual Studio 2014, you may have seen some odd changes in the new version. It was a source of frustration for me, when I would start with a working template, then move to a different file only to have the template be invalid or stop working in some strange way.

An informal poll of my teammates revealed that some had seen this happen, and some never had a problem, so it’s obviously hit-or-miss as to whether your setup will cause this issue. But if you’re reading this article, chances are you’re one of the lucky ones! Anyway, after several attempts at fixing the settings, I finally found one that worked. Apparently Visual Studio was helpfully formatting my new html (my template), which included adding line breaks and fixing capitalization for me. Thanks, but no thanks – it was causing more problems than it solved.

So, here’s the option to disable this feature, found in the Options dialog under Visual Studio.

2014-12-23 11_08_15-SchoolManagementSystem - Microsoft Visual Studio

 

There, maybe it will help someone else out as well!

The post Stop Kendo Template Capitalization Mishaps in Visual Studio 2014 Copy/Paste appeared first on Falafel Software Blog.

The Best Developer Articles of 2014

$
0
0

AngularJSIt’s a new year, sure, but we we’re not quite ready to give up our most popular articles of 2014. From simple tips to deep dives into code, these posts have it all!

AngularJS and Kendo UI – Part 1 – Getting Started

We’re bringing together two themes I’ve been developing for the past few months: AngularJS and Kendo UI. These technologies go together like peanut butter and chocolate, and both share two characteristics that are critical to this series:

  • The technology is hot, desirable and useful
  • The reference documentation is very good, but good tutorials are in short supply

Read the Article Now

Remote Desktop on a High-DPI Screen

In this blog post, my intention is not to show you how to use DPI-scaling in Windows, but to let you know about a solution I found to one of the more annoying issues I’ve discovered so far with using DPI-scaling: Remote Desktop is not DPI scaling-aware. After I scaled my screen down to full-HD (a simulated 1920 x 1080 starting at 3200 x 1800 at 167% scaling), I opened a remote desktop session to a server I help maintain and immediately noted that it was displayed at my monitor’s full native resolution. It was ignoring my scaling settings, which made everything almost impossible to read.

Read the Article Now

iOS Web Inspector on Windows with Telerik AppBuilder

If you have a Mac, you already have tools to inspect and debug web pages on your iOS device. But what if you need to troubleshoot a problem with a web application on iPad when you are running Windows? Google Chrome Developer Tools has Emulation options to run a tab as an iPad in your desktop browser, but it will never be a perfect representation of how the web page will work on an iOS device.

Read the Article Now

Three steps to use jQuery UI in ASP.NET MVC 5

Many developers struggle to work with jQuery UI in an ASP.NET MVC application. In this post, I will show you three steps required to start working with jQuery UI in an ASP.NET MVC application. At the end of the post we will take a look at working with the autocomplete widget. These three steps will let you work with jQuery UI in an ASP.NET MVC application.

Read the Article Now

Understanding IEnumerable and IQueryable in C#

A C-Sharp developer is always puzzled about usage of the following interfaces:

  • IEnumerable
  • IQueryable
  • ICollection
  • IList

I see developers are not that confident about usage of the mentioned interfaces. In this post, I am going to discuss basic differences among IEnumerable and IQueryable and in which scenario to use what.

Read the Article Now

We’re looking forward to another year of learning! Is there something you’d like to like to see us write about? Tweet at us @falafelsoftware!

The post The Best Developer Articles of 2014 appeared first on Falafel Software Blog.

Testable ViewModels with Kendo and Jasmine

$
0
0

Introduction

This post is the first in what I hope becomes a series chronicling my journey from completely untestable code to code that is covered with tests from database to browser. Figuring out where to get started with testing can be tricky, especially when you aren’t used to writing code designed to be testable. However, I’ve gotten my first good foothold, and of all places, it’s in the extremeties: the JavaScript that governs the UI logic in the browser. I think it’s pretty cool, so let’s get right to it!

The Basics

In my everyday work, I use Kendo as the framework that my webpages are built upon and I’m already a huge fan of MVVM just because it lets me write less code and focus on developing the specific logic the page calls for rather than waste time reading and writing to various HTML elements. I just manipulate the ViewModel and let the bindings handle the visual representation. Now imagine if you could develop a ViewModel that you could put into a test harness and confirm that it behaves correctly without even having a UI developed yet. That’s precisely what I’m going to demonstrate.

First of all, we want to be able to define the ViewModel behavior in its own “class” (in quotes because JavaScript doesn’t have true classes) so that there can be more than one instance of it: one to be bound to the UI and one to go into a test harness. That way, when the tests run, the UI wont’t act like it’s been possessed by a hyper-manic poltergeist because the tests are manipulating their own unbound instance. The typical way of creating a ViewModel does not allow for this.

var viewModel = kendo.observable({
    message: 'Hello world!'
});
// Can't create another instance of viewModel. Boo!

However, if you just make a slight change to the way you declare a ViewModel class, you can accomplish the goals stated above. All kendo.observable() does is wrap the object you pass it in an ObservableObject instance. So what if you define your own custom ObservableObject subclass?

var TestableViewModel = kendo.data.ObservableObject.extend({
    message: 'Hello world!'
});
// New instances can be created with new TestableViewModel() and they'll all have their own observable message property!

At its core, that’s really all you have to do in order to get started writing your own testable ViewModel classes. There are some challenges when it comes to testing DataSources, and that will be the subject of my next post. Meanwhile, please take a look at this JSBin to see a fully functional, if trivial, application that takes the above concept and fleshes it out to include a bound UI and a small suite of Jasmine unit tests operating on their own private instances of the same ViewModel.

The post Testable ViewModels with Kendo and Jasmine appeared first on Falafel Software Blog.

Kendo ObservableObject subclasses: prototype vs init

$
0
0

An Unscheduled Detour

I said that my next post was going to be about how to test Kendo DataSources using the techniques I described last time, but I noticed something about the last code sample that I don’t like, so instead this time I’m going to call that out and show how to fix it. I promise I will talk about testing DataSources next time!

So what’s wrong with the last bit of code that I linked to? Well, from a functional point of view, nothing. The code works as expected. However, if you take a look at the state of the object, you might notice something a little odd.AddingViewModel

Take a look… Do you see it yet? Let’s take a look at it again after the test runs.AddingViewModel2

Now do you see it? The original values are still there in the prototype of the object. Now again, functionally, the object works as expected because of how JavaScript identifier resolution works: attempt to resolve the identifier against the object instance, and if that fails, move up the prototype chain and try again. However, once I saw this I knew I had to fix it. For one thing, it’s just not right that data that is meant to belong to individual instances would exist in the prototype. For another, this could actually be the source of a subtle bug. Consider this example, based on the sample I linked in the last blog:

var AddingViewModel = kendo.data.ObservableObject.extend({
  value1: 1,
  value2: 2,
  value3: null,
  button_click: function(e) {
    this.compute();
  },
  compute: function() {
    this.set('value3', this.get('value1') + this.get('value2'));
  }
});

describe('AddingViewModel', function() {
  var testAddingViewModel;
  
  beforeEach(function() {
    testAddingViewModel = new AddingViewModel();
  });
  
  afterEach(function() {
    testAddingViewModel = null;  
  });
  
  it('Deleting a property should completely remove it', function() {
    testAddingViewModel.set('value1', 10);
    delete testAddingViewModel.value1;
    expect(testAddingViewModel.get('value1')).toBe(undefined); // FAIL! It will read from the prototype and return 1!
  });
});

So what is the alternative, you might ask? We want to set up data fields on each instance of the AddingViewModel, rather than the prototype. When extending a Kendo class, the answer is to perform the initialization in the init() function. This is the name that Kendo uses for the class initializer function. In order to support inherited behavior, you must explicitly call the parent type’s initializer. In this case, the parent class is kendo.data.ObservableObject. The init function is an instance method, not a static method, so you must access the class’ prototype in order to call it. In Kendo, the class prototype is aliased as fn. Finally, you want to make sure that you specify that the initializer should use “this” object as the context, so you use either .call() or .apply() to do so. I prefer to use .apply(this, arguments) because it’s generic; it works without requiring special knowledge of the parent class’ initializer parameters (though they must still be provided when creating an instance of the subclass) Let’s take a look:

var AddingViewModel = kendo.data.ObservableObject.extend({
  init: function() {
    kendo.data.ObservableObject.fn.init.apply(this, arguments);
    this.set('value1', 1);
    this.set('value2', 2);
    this.set('value3', null);
  },
  button_click: function(e) {
    this.compute();
  },
  compute: function() {
    this.set('value3', this.get('value1') + this.get('value2'));
  }
});

If you replace the definition of AddingViewModel in the previous snippet with this one, the test will pass, so that solves the problem. If you inspect an instance of AddingViewModel, you will find what you would expect: that the value fields are on the instance, while the functions are in the prototype.

There is also another way you could write the init() override if you prefer. ObservableObject.fn.init() automatically copies all properties of the first argument passed and wraps object and array properties in ObservableObject and ObservableArray instances. So rather than setting their defaults after the fact, you could do something like this:

var AddingViewModel = kendo.data.ObservableObject.extend({
  init: function() {
    kendo.data.ObservableObject.fn.init.call(this, {
      value1: 1,
      value2: 2,
      value3: null
    });
  },
  button_click: function(e) {
    this.compute();
  },
  compute: function() {
    this.set('value3', this.get('value1') + this.get('value2'));
  }
});

But both of these approaches ignore or overwrite a value object that the caller might pass in. So an even better approach would be to create defaults and then allow the caller to override:

var AddingViewModel = kendo.data.ObservableObject.extend({
  init: function(values) {
    var defaultValues = {
      value1: 1,
      value2: 2,
      value3: null
    };
    kendo.data.ObservableObject.fn.init.call(this, $.extend({}, defaultValues, values));
  },
  button_click: function(e) {
    this.compute();
  },
  compute: function() {
    this.set('value3', this.get('value1') + this.get('value2'));
  }
});

For all this plus an updated suite of unit tests, please check this JSBin link.

So to recap, I noticed that setting default data values in the custom ViewModel’s prototype leaves you open to subtle bugs. I recommend that you put functions into the prototype definition and initialize instance-specific defaults in the init() function instead. Next time I promise I will get back on track and talk about testing Kendo DataSources!

The post Kendo ObservableObject subclasses: prototype vs init appeared first on Falafel Software Blog.

How to use SignalR with Kendo UI

$
0
0

Why SignalR?

For most Kendo projects that I’ve been involved with, Kendo UI consumes JSON data originating from an ASP.NET controller (either a JsonResult action or a WebAPI action). The lifecycle is pretty straight-forward: the DataSource reads the initial data, and then a separate AJAX postback is performed for each create, update, and destroy operation.

The problem with this is that the user is looking at a snapshot of the data. Suppose that another user is also looking at that data, and decides to change it. How do we alert the first user that their data is stale and needs to be refreshed?

For ASP.NET projects, we can introduce SignalR as a real-time messaging layer. In the simplest use case, when one client changes the data, SignalR would just be used to notify every other client that their data is stale so they could then re-fetch it. But, this would not be taking advantage of Kendo UI’s first-class support for SignalR within the DataSource itself!

Kendo UI offers the ability to map the DataSource transport actions (read, create, update, and destroy) to SignalR Hub method names. This merely swaps out the role of WebAPI for a SignalR Hub. But, the DataSource also allows push methods to be defined, and this is where things get interesting. See, with SignalR, the server can invoke methods that are defined on the client. So, when a user updates a record, that record’s data can be pushed to all of the other clients, and Kendo will take care of updating its in-memory version of that record with the new version.

Implementation

The basic configuration is pretty straightforward:

var dataSource = new kendo.data.DataSource({
    type: "signalr",
    schema: {
        model: {
            id: "ID",
            fields: {
                "ID": { editable: false }
            }
        }
    },
    transport: {
        signalr: {
            promise: hubStart,
            hub: hub,
            server: {
                read: "read",
                update: "update",
                destroy: "destroy",
                create: "create"
            },
            client: {
                read: "read",
                update: "update",
                destroy: "destroy",
                create: "create"
            }
        }
    }
});

 

Some things to note:

  • The “type” is set to “signalr”
  • You must have an “id” defined in the schema model
  • You must have a “promise” and “hub” defined in the transport (more on that below)
  • The “server” CRUD actions map to SignalR Hub method names. You do not need to map all if they aren’t going to be used.
  • The “client” CRUD actions map to what the SignalR Hub thinks the client function names are. You do not need to map all if they aren’t going to be used.

The corresponding SignalR Hub for this DataSource may resemble the following:

public class SimpleHub : Microsoft.AspNet.SignalR.Hub
{
    public IEnumerable<SomeEntity> Read()
    {
        var ret = new List<SomeEntity>();

        // Fill the list

        return ret; 
    }

    public void Update(SomeEntity entity)
    {
        // validation
        // commit changes to database

        Clients.Others.update(entity);
    }

    public SomeEntity Create(SomeEntity entity)
    {
        // validation
        // commit changes to database

        Clients.Others.create(entity);
    }

    public void Destroy(SomeEntity entity)
    {
        // validation
        // commit changes to database

        Clients.Others.destroy(entity);
    }
}

Notice that for Update, Create, and Destroy, the Hub uses “Client.Others.{action}” to push the updated entity to all other clients who are currently connected to this Hub.  The “{action}” name here is what must be mapped in the transport.signalr.client options of the DataSource.

Of course, there are times when data may be updated elsewhere in your system, instead of being performed via one of the Hub methods. That’s okay, because clients connected to a hub can still be notified by first getting a reference to that Hub’s context, and then calling the same client-side function that the Hub’s code would have used:

var context = GlobalHost.ConnectionManager.GetHubContext<SimpleHub>();
context.Clients.All.update(entity);

Note: In the Hub methods, we used “Clients.Others” in order to notify everyone except who made the actual change (because they are already aware of the change).  Here, we use “Clients.All” to notify everyone, because the assumption is that the data was not changed by one of the clients, therefore everyone must be notified.

Bootstrapping

There is a bit of bootstrapping that is required for SignalR on page load, and care must be taken to not call SignalR methods before its bootstrapping is complete.

First, the SignalR JQuery plug-in must be included in your page’s scripts.  Then, the server’s SignalR handler needs to be called in order to retrieve metadata that is specific to the web app.  For ASP.NET, I prefer to do this in my Master Page or Layout View, especially if SignalR is used across many different views:

<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>

Note: If you are new to SignalR, the “/signalr/hubs” route is handled at runtime to generate JavaScript containing functions and details about your available Hubs and Hub methods (the server uses Reflection to discover the Hub classes that available in your application’s assemblies). This populates an object graph that is accessible from $.connection in JavaScript.

Next, when the document is ready, the SignalR connection to the server can be initiated. This causes SignalR to negotiate the best form of persistent connection that is supported by both the browser and the server (i.e., WebSockets, Server-Side Events, Long Polling, etc):

$(function () {
    var hub = $.connection.simpleHub;
    var hubStart = $.connection.hub.start();

$.connection.hub.start() returns a JQuery Deferred object (which implements a Promise). This is the “promise” object that the DataSource configuration is looking for in transport.signalr.promise.  After SignalR has completed its bootstrapping, the promise will be marked as resolved, and then any actions that have been chained onto that promise will be executed. The DataSource uses this as the means of waiting for the bootstrapping to complete before it tries to perform the first “read” action (if it tried to invoke a SignalR function before bootstrapping was complete, then an exception would be raised).

Also notice that $.connection.simpleHub is the JavaScript object on the client that proxies the C# class on the server. This is the object that the DataSource configuration is looking for in transport.signalr.hub.

Possible Uses

The are many applications where always being connected to the server and always having the latest information may be useful. Some examples may include:

  • A list of system events, alerts, or exceptions that are displayed in the browser (automatically updated as new events occur)
  • A project time sheet (grid) that is being worked on simultaneously by multiple people
  • Real-time charting of instrument data
  • Financial data that is subject to constant change, such as stock prices or currency conversion rates.
  • Shopping cart with real-time inventory/indication of backordered items before the order is placed
  • Dropdown list of concert ticket types filtered to the up-to-the-second availability

The post How to use SignalR with Kendo UI appeared first on Falafel Software Blog.


Falafel Team Selected as Telerik Developer Experts

$
0
0

Telerik recently announced the launch for their new Telerik Developer Network, and with it the Telerik Developer Experts program. We’re excited to say that Telerik chose not just one, but FOUR of our fantastic Falafel team to be Telerik Developer Experts. The Developer Experts program recognizes members of the Telerik Developer Network community who have gone above and beyond to share their knowledge and contribute to the community, but are also experts in one or more of Telerik’s tools. We’re very proud of our CEO, Lino Tadros; Master Consultant, Jesse Liberty; Senior Software Engineer, Keith Burnell; and Software Architect, Venkata Koppaka for being selected into the Developer Experts program.

Congratulations Lino, Jesse, Keith, and Venkata!

Read Full Story Here

P.S. Need some help using Telerik’s tools? We’re Telerik Platinum Partners! Learn more here.

The post Falafel Team Selected as Telerik Developer Experts appeared first on Falafel Software Blog.

Testing a Kendo ViewModel DataSource

$
0
0

Welcome to the next step on the road to testing! So far I’ve shown a way to take the ordinary, one-off way of defining ViewModels and moving towards defining a ViewModel “class” so that one can be bound to the UI and others can be unit tested. I also took a detour to explain some nuances of how defining Kendo classes work with regards to what goes into a class’ prototype versus what goes into a specific instance. This time, I am going to take these concepts and discuss some specific complications you might encounter when attempting to test a DataSource, and how to solve those problems.

The first thing you’ll have to decide when adding a DataSource to an ObservableObject subclass is, where to declare it? Thinking back to the last post, you already know that if you define the DataSource outside of the init function, that property will become part of the prototype, shared with all instances of the subclass. I think we would want each instance to have its own data, so for the majority of cases, you should add the DataSource definition during the init function.

When you have a ViewModel with a DataSource in it, one thing you might want to be able to do is to have some properties on the ViewModel that are used by the DataSource when making server requests. If that ViewModel was created the “normal” way by initializing a variable with kendo.observable(), then it’s easy to read the ViewModel instance just by referencing the variable. But how do you accomplish the same task when you define the ViewModel as a class instead of as an instance? It’s actually quite simple: obtain the self-reference within init() and then reference it from within other functions declared in init()’s function scope. For example, see this snippet:

init: function(values) {
    var self = this,
        defaultValues = {
          blogCount: 2
        };
    kendo.data.ObservableObject.fn.init.call(this, $.extend({}, defaultValues, values));
    this.set('dataSource', new kendo.data.DataSource({
      transport: {
        read: {
          url: 'blog.falafel.com/api/adam-anderson/',
          data: function() {
            return {
              type: 'recent',
              count: self.blogCount
            };
          }
        }
      },
      schema: {
        data: 'data'
      }
    }));
  }

In this example, a self-reference is obtained and then the ViewModel is initialized with a property named blogCount. Next, a DataSource is added with a function provided for the read transport’s data option. This function will be called any time the DataSource makes a read request, and it will use the self-reference obtained in init()’s function scope to read from this instance of the ViewModel.

AJAX mocking with Jasmine

Jasmine provides the ability to mock AJAX results with an optional module that you must explicitly reference and install into Jasmine before using it. There are a number of ways to use it, but for this example, I’m going to show the simplest approach, which is to perform the setup and teardown within a test method. It’s possible to perform the same tasks in a suite’s setup and teardown functions instead as well as predefine certain responses to specific requests as well. Let’s take a look at the example:

it('can test DataSources', function() {
    jasmine.Ajax.withMock(function() {
      viewModel.set('blogCount', 3);
      viewModel.dataSource.fetch(); // Sends AJAX request which is caught by Jasmine.Ajax
      var dataSourceRequest = jasmine.Ajax.requests.mostRecent();
      // You can inspect the URL
      expect(dataSourceRequest.url).toEqual('blog.falafel.com/api/adam-anderson/?type=recent&count=3');
      // You can specify a response synchronously
      dataSourceRequest.response({
        'status': 200,
        'contentType': 'application/json',
        'responseText': '{"data":[{"title":"Testable ViewModels with Kendo and Jasmine","date":"1/20/2015"},{"title":"Kendo ObservableObject subclasses: prototype vs init","date":"1/23/2015"},{"title":"Testing Kendo DataSources (working title)","date":"2/10/2015"}]}'
      });
      // Now the DataSource should contain the data
      expect(viewModel.dataSource.data().length).toEqual(3);      
    });
  });

Let me break this down for you step by step. First of all, you make a call to jasmine.Ajax.withMock and pass a function containing the steps to test. This test starts by setting the blogCount property and then telling the DataSource to make a request. Since this is occurring within withMock(), the AJAX request is caught by Jasmine and will not respond until you tell Jasmine what to respond with. At this point, you can inspect the request to perform tests on it. This test expects that the DataSource will make a request passing the blogCount value to the server in the QueryString variable ‘count’. Next, the test provides a response. Note that this response must be valid JSON, so for example, all the property names must be enclosed in double quotes. One simple way to obtain this raw JSON response is to make a real request to the server and then use a tool like the Chrome Dev Tools to obtain the raw response and paste it into your test. Lastly, the the test validates that the DataSource is correctly configured to parse the server response, which returns the data in a property named ‘data’. As usual, I have a full working sample available on JSBin.

With this technique, you now have the ability to define and test a wide range of logic within a ViewModel. The goal should be for all of the page or section’s behavior to be expressed within the ViewModel and completely ignorant of the presence (or absence) of a DOM. Of course, sometimes this is not 100% possible; for example, if your page needs to perform some custom animations, then the animations do need to reference the DOM. However, consider moving those animations to custom MVVM bindings, as demonstrated here. The more you can move the UI-specific code into bindings and out of the ViewModel, the more testable the ViewModel will be!

The post Testing a Kendo ViewModel DataSource appeared first on Falafel Software Blog.

Custom Skin for Kendo UI DataViz Components

$
0
0

Kendo UI DataViz is a collection of components targeting data visualization such as charts, gauges and diagrams. These elements are indispensable in any application that deals with data aggregation and data presentation.

When you develop an application, it is seldom that you are satisfied with the default theme (or the other themes) that Kendo UI offers because oftentimes you need to make your application look and behave like the original mockups that the designers put together.

Just like other popular presentation frameworks, Kendo UI offers a Theme Builder that allows you to create your “unique” and custom theme. With a bit of help from the designers, you can, with a few clicks, make Kendo UI Components look very close to the desired appearance.

Whether it’s for Web or Mobile, you can easily make use of the final LESS or CSS file that the Theme Builder produces. In the case of DataViz widgets, it isn’t trivial. If you include the JavaScript file that the Theme Builder gives you, you will not see any change in your application. You would have to manually apply it to the DataViz components. Here’s how to create a custom skin for Kendo UI DataViz:

Once you create the DataViz theme, you export a JavaScript file (not LESS and not CSS) that looks like this:

kendo.dataviz.ui.registerTheme('awesometheme', {
    "chart": {
        "title": {
            "color": "#8e8e8e"
        },
        "legend": {
            "labels": {
                "color": "#232323"
            }
        },
        "chartArea": {
            "background": "rgba(0, 0, 0, 0)"
        },
        "seriesDefaults": {
            "labels": {
                "color": "#000"
            }
        },
        "axisDefaults": {
            "line": {
                "color": "#ffffff"
            },
            "labels": {
                "color": "#232323"
            },
            "minorGridLines": {
                "color": "#ffffff"
            },
            "majorGridLines": {
                "color": "#ffffff"
            },
            "title": {
                "color": "#232323"
            }
        },
        "seriesColors": [
            "#66c39e",
            "#f15b4e",
            "#66c39e",
            "#f15b4e",
            "rgba(0, 0, 0, 0)",
            "rgba(0, 0, 0, 0)"
        ],
        "tooltip": {
            "background": "#fff",
            "color": "#424a55",
            "opacity": 1
        }
    },
    "gauge": {
        "pointer": {
            "color": "#f15b4e"
        },
        "scale": {
            "rangePlaceholderColor": "#dedede",
            "labels": {
                "color": "#2e2e2e"
            },
            "minorTicks": {
                "color": "#2e2e2e"
            },
            "majorTicks": {
                "color": "#2e2e2e"
            },
            "line": {
                "color": "#2e2e2e"
            }
        }
    }
});

You then need to include this JavaScript file after Kendo DataViz and then call the following:

//Override the theme for dataviz widgets
            var themable = ["Chart", "TreeMap", "Diagram", "StockChart", "Sparkline", "RadialGauge", "LinearGauge"];

            if (kendo.dataviz) {
                for (var i = 0; i < themable.length; i++) {
                    var widget = kendo.dataviz.ui[themable[i]];

                    if (widget) {
                        widget.fn.options.theme = "awesometheme";
                    }
                }
            }

In this snippet, we are looping through all the dataviz components and overriding the theme name with our “awesometheme”. Pretty simply ey!

Now you wonder, what if you extended the built-in widget and created your own plugins?

 

// Extended Kendo widget
    kendo.ui.plugin(kendo.dataviz.ui.Chart.extend({

        init: function (element, options) {
            
            var mergedOptions = $.extend(true, {}, this.options, options);

            // Base call to widget initialization
            kendo.dataviz.ui.Chart.fn.init.call(this, element, options);
        },

        options: {
            name: 'AwesomeChart'
        }
    }));

 

In this snippet, we have created our own extension of the Chart component and we called it “AwesomeChart”. So how do we override the theme for our “AwesomeChart” programmatically?

//Override the theme for dataviz widgets
            var themable = ["Chart", "TreeMap", "Diagram", "StockChart", "Sparkline", "RadialGauge", "LinearGauge"];

            if (kendo.dataviz) {
                for (var i = 0; i < themable.length; i++) {
                    var widget = kendo.dataviz.ui[themable[i]];

                    if (widget) {
                        widget.fn.options.theme = "awesometheme";
                    }
                }
            }

            //Override the theme for custom plugins
            if (kendo.ui.AwesomeChart)
                kendo.ui.AwesomeChart.fn.options.theme = "awesometheme";

Yay! we did it with only 2 lines of code. Are you still questioning why we love Kendo UI?

 

The post Custom Skin for Kendo UI DataViz Components appeared first on Falafel Software Blog.

Make a Kendo MVVM calculated field depend on DataSource data

$
0
0

Imagine this: You are developing a web page that displays data in a grid but you also want to be able to show various other views and aggregations outside the grid. How would you do it? You could hook up event handlers to the grid’s DataSource and manually update everything when the data changes. But wouldn’t it be nicer if you could just declare MVVM bindings and let the bindings detect all the changes? I think so. Let me know you how it’s done.

Scalar bindings

First, let’s talk about scalar bindings such at the text and value bindings. You should already know from the Kendo docs that in order for a function to act as a dependent property, you must access other ObservableObject properties using the get method. But how do you do that with a DataSource? Take the following setup (JSBin link):

<div data-role="grid" data-bind="source:gridSource"
       data-editable="true">
  </div>
  <label>
    Total Quantity:
    <input data-bind="value: quantitySum">
  </label>
var viewModel = kendo.observable({
  gridSource: new kendo.data.DataSource({
    data: [
      { category: 'Dogs', quantity: 4 },
      { category: 'Cats', quantity: 3 },
      { category: 'Apples', quantity: 12 },
      { category: 'Oranges', quantity: 8 },
      { category: 'PCs', quantity: 5 }
    ]
  }),
  getGridData: function() {
    return this.gridSource.data();
  },
  quantitySum: function() {
    return _.reduce(this.getGridData(), function sum(total, item) {
      return total + item.get('quantity');
    }, 0);
  }
});

kendo.bind(document.body, viewModel);

In this case, when you edit the items in the grid, the value bound to quantitySum will not update. If you dig deeper, you will find that using get(‘quantity’) does not actually create a dependency. But there is a way to create one and it’s quite simple if perhaps not quite intuitive or documented. Simply access the data like this:

getGridData: function() {
    return this.get('gridSource').data();
  }

By specifying get(‘gridSource’), you create a dependency on the DataSource so that when data within it changes, all scalar bindings will update. (JSBin link)

Source binding

I keep using that word “scalar” to qualify my statements about dependent MVVM functions and here’s why: the same behavior will not occur with a source binding. So for example, if you have this chart and dependent data defined, the chart will not update even though the textbox does: (JSBin link)

<div data-role="chart" data-bind="source:getChartSource"
       data-series="[{
                      field: 'quantity'
                    }]"
       data-category-axis="{
                             field: 'category'
                           }">
  </div>
getChartSource: function() {
    var gridData = this.getGridData();
    return [
      {
        category: 'Cats & Dogs',
        quantity: gridData[0].get('quantity') + gridData[1].get('quantity')
      },
      {
        category: 'Apples & Oranges',
        quantity: gridData[2].get('quantity') + gridData[3].get('quantity')
      },
      {
        category: 'Apples & PCs',
        quantity: gridData[2].get('quantity') + gridData[4].get('quantity')
      }
    ];
  }

From my reading of the Kendo source code, this is intentional. The source binding is only supposed to bind a set of data as a DataSource to a widget; past that point the only thing the source binding cares about is whether the entire source is refreshed, in which case it will update dependent MVVM bindings. I suspect the intention here was that changes to individual items within a DataSource are supposed to be handled by the DataSource rather than by MVVM bindings. So you will have to write some code in order to notify MVVM to refresh the binding. Here are three options:

The first option is just to make MVVM think that the entire DataSource has been replaced, forcing it to refresh all dependent bindings. You can accomplish this by raising a change event with the correct event parameters filled: (JSBin link)

viewModel.trigger('change', { field: 'getChartSource' });

The nice thing about this approach is that it takes the least code and will notify all dependent MVVM bindings. You don’t have to obtain individual widget references and call their refresh methods. The slightly icky thing about this is that it does depend on the Kendo implementation of MVVM change notifications, so there is always a chance that this code will stop working at some future date if the internal implementation changes.

The next option is to do the same thing as above but without depending on any kind-of-private implementation details. Create an observable array that the chart is bound to and manipulate the array: (JSBin link)

<div data-role="chart" data-bind="source:chartSource"
       data-series="[{
                      field: 'quantity'
                    }]"
       data-category-axis="{
                             field: 'category'
                           }">
  </div>
change: function(e) {
      viewModel.set('chartSource', viewModel.getChartSource());
    }
  }),
  chartSource: [],
  getChartSource: function() {

This take slightly more code but keeps you from depending on the parameter structure of the Kendo MVVM change event.

The final option takes the most code, but does have one important difference from the first two: the first two completely refresh the dependent data source, which may perform worse than updating only the changed items. This final example illustrates how one might perform the least amount of data change. (JSBin link)

change: function(e) {
      if (!e.action) {
        // No action means a read or complete refresh
        viewModel.set('chartSource', viewModel.getChartSource());
      } else if (e.action == 'itemchange') {
        var gridData = viewModel.getGridData(),
            item = e.items[0];
        switch (item.get('category')) {
          case 'Dogs':
          case 'Cats':
            viewModel.chartSource[0].set('quantity', gridData[0].get('quantity') + gridData[1].get('quantity'));
            break;
          case 'Apples':
            viewModel.chartSource[1].set('quantity', gridData[2].get('quantity') + gridData[3].get('quantity'));
            viewModel.chartSource[2].set('quantity', gridData[2].get('quantity') + gridData[4].get('quantity'));
            break;
          case 'Oranges':
            viewModel.chartSource[1].set('quantity', gridData[2].get('quantity') + gridData[3].get('quantity'));
            break;
          case 'PCs':
            viewModel.chartSource[2].set('quantity', gridData[2].get('quantity') + gridData[4].get('quantity'));
            break;
        }
      }
    }

Given the amount of code it takes to do this more precise update, I would probably recommend you start with one of the first two techniques and only move to this one once performance becomes a priority.

The post Make a Kendo MVVM calculated field depend on DataSource data appeared first on Falafel Software Blog.

Sitefinity Asynchronous Search with WebAPI

$
0
0

Overview

Sitefinity CMS features a powerful internal Search Engine that allows your site visitors to search your content and find what they are looking for. The Search Engine is built on top of the .NET port of the infamous Lunene Engine which powers an unlimited number of websites today.

Unlike the solid Search Engine behind it, the Search Widget which Sitefinity offers is not as mature. It provides the options to set up a basic search page and returns the results in a form of a list. Perhaps that will be satisfactory in most cases, but what if your requirements exceed those of a simple search?. What if you’d like to create an Amazon-like search page for books or products?

It’s that sort of transition !

Game of thrones

Wait, I’ve customized Search Before

It’s possible that you have been there before, and that you have extended the Search widget with the help of great blog posts such as this one by Svetla. There is no denial that the team did a formidable job explaining how to extend and customize every part of the CMS, whether it’s through the documentation portal, blog posts, forums or several webinars. Search is still missing its asynchronous nature and there is no way that we can build our own interface for the search page while making use of a Search service which searches the appropriate index for us. Furthermore, it’s almost impossible to search Sitefinity content from another client so the idea of creating Content Driven Mobile Apps is hindered by the inadequacy of the Search Widget.

Worry not, we’ve got you covered

I put together an asynchronous implementation of the Sitefinity Search using Web API. I leveraged as much as possible the code from the Search Widget so it respects the settings of your site. It consists of one API Controller with a single action:

[HttpGet]
        public SearchResultModel Get(string searchTerm, int skip = 0, int take = 5)
        {
            var model = new SearchResultModel {Term = searchTerm};
            int hitCount;

            var results = new List<SearchDocumentModel>();
            
            Search(searchTerm, Catalogue, skip, take, out hitCount).ForEach(s => results.Add(Models.ModelFactory.Create(s)));
            
            model.Count = hitCount;
            model.Results = results;

            return model;
        }

The Search Result Model class defines the structure of the search result data:

public class SearchResultModel
    {
        public string Term { get; set; }
        public int Count { get; set; }
        public IEnumerable<SearchDocumentModel> Results { get; set; } 
    }

The repo is hosted on Github and it will be a good starting point for you if you want to put together advanced searching capabilities on your site. You will need to follow the Installation instructions on Github. Once configured, you can start hitting the end point and searching your content. You can check out the search page that’s included under “Tests”.

Conclusion

With the help of Web API, we can rewrite our search pages (using JavaScript) and asynchronously search a Sitefinity site. This will dramatically improve the search experience on your site and eventually leads to increasing your conversion rate.

 

 

The post Sitefinity Asynchronous Search with WebAPI appeared first on Falafel Software Blog.

Viewing all 43 articles
Browse latest View live