KendoUI using templates in Menus: Yes, we can!


Is it possible using template in KendoUI Menus? No, as it is (out of the box) But of course you can with very little programming.

KendoUI Menu: the basics

Creating a Menu with Kendo UI is pretty simple, just define a list of items and then invoke kendoMenu.

This is the HTML code:

<ul id="menu">
    <li>
        Europe
    </li>
    <li>
        Americas
    </li>
    <li>
        Asia
    </li>
</ul>

and this is the JavaScript:

$(document).ready(function () {
    $("#menu").kendoMenu();
});

And it looks like:

Basic Kendo UI menu
Basic Kendo UI menu

KendoUI Menu: nested options

Nesting options in Kendo UI menu is as simple as before, just define nested lists in your top level list.

Now, HTML looks like:

<ul id="menu">
    <li>
        Europe
    </li>
    <li>
        Americas
        <ul>
            <li>
                North America
                <ul>
                    <li>Canada</li>
                    <li>United States</li>
                    <li>Mexico</li>
                </ul>
            </li>
            <li>Central America</li>
            <li>South America</li>
        </ul>
    </li>
    <li>
        Asia
    </li>
</ul>

And now, it looks like:

KendoUI Menu: nested options
KendoUI Menu: nested options

KendoUI: using datasource initialization

But we don’t have to initialize the Menus from HTML list, we can also use KendoUI datasource. The initialization of previous menu is:

HTML code:

<div id="menu"></div>

And the JavaScript:

$(document).ready(function () {
    $("#menu").kendoMenu({
        dataSource: [
            {
                text : "Europe"
            },
            {
                text : "Americas",
                items: [
                    {
                        text : "North America",
                        items: [
                            { text: "Canada" },
                            { text: "United States" },
                            { text: "Mexico" }
                        ]
                    }
                ]
            },
            {
                text   : "Asia"
            }
        ]
    });
});

KendoUI Menu: Customizing it

There are a few option pretty useful for customizing a Menu item. Most important are:

  • imageUrl: URL to an image displayed before the item text.
  • spriteCssClass: CSS class for displaying an image before the item text.
  • cssClass: CSS class for menu item.

Modifying our previous example as follow:

JavaScript code:

$(document).ready(function () {
    $("#menu").kendoMenu({
        dataSource: [
            {
                text: "Europe"
            },
            {
                text : "Americas",
                items: [
                    {
                        text : "North America",
                        items: [
                            { text: "Canada" },
                            { text: "United States" },
                            { text: "Mexico" }
                        ]
                    },
                    { text: "Central America" },
                    {
                        text : "South America",
                        items: [
                            { text: "Argentina", cssClass: "ob-red", spriteCssClass: "ob-flag-argentina"  },
                            { text: "Brazil", imageUrl: "images/flags/brazil.png" },
                            { text: "Chile", cssClass: "ob-green" }
                        ]
                    }
                ]
            },
            {
                text: "Asia"
            }
        ]
    });
});

and the CSS classes are defined as:

.ob-flag-argentina {
    background-image: url('images/flags/argentina.png');
}

.ob-red {
    background-color: red !important;
    color: white !important;
}

.ob-green {
    background-color: green !important;
    color: white !important;
}

And it would look like:

KendoUI Menu: customizing apperance
KendoUI Menu: customizing apperance

KendoUI Menu: using HTML in text

Next step is using your own HTML as text for an item. This is also supported by defining the item as:

{
    text: "Asia",
    items : [
        { text: "<span style='border: 1px solid red;'>China</span>", encoded: false },
        { text: "<span style='border: 1px solid blue;'>India</span>", encoded: false }
    ]
}

and looks like:

KendoUI Menu: defining  item as HTML
KendoUI Menu: defining item as HTML

KendoUI Menu: using templates

I know that documentation on Kendo UI Menu is not good but there is no template option in KendoUI Menu, I had to do it by myself. Here I show you what you need to do.

The idea about the implementation

What I’m going to be doing is crawling the DataSource structure looking for each item if they have a template entry. If so, I use it as a template definition, using the result of expanding the template as text of item and setting encoded to false.

And this is the recursive function that crawls the data applying the template:

function transformText(nodes) {
    for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        if (node.template) {
            var template = kendo.template($("#" + node.template).html());
            node.text = template(node);
            node.encoded = false;
            // Remove this from node to do not get it twice
            node.spriteCssClass = undefined;
            node.imageUrl = undefined;
            node.cssClass = undefined;
        }
        if (node.items) {
            transformText(node.items);
        }
    }
    return nodes;
}

and the Menu initialization would be:

$("#menu").kendoMenu({
    dataSource: transformText([
        {
            text : "Europe",
            items: [
                { text: "Bulgaria", imageUrl: "images/flags/bulgaria.png" },
                { text: "Germany", imageUrl: "images/flags/germany.png" },
                { text: "Spain", imageUrl: "images/flags/spain.png" }
            ]
        },
        {
            text : "Americas",
            items: [
                {
                    text : "North America",
                    items: [
                        { text: "Canada", spriteCssClass: "ob-flag-canada"  },
                        { text: "United States", spriteCssClass: "ob-flag-usa" },
                        { text: "Mexico", spriteCssClass: "ob-flag-mexico"  }
                    ]
                },
                {
                    text : "Central America",
                    items: [
                        { text: "Costa Rica", template: "template", id: 2, spriteCssClass: "ob-flag-costa-rica" },
                        { text: "Nicaragua", template: "template", cssClass: "ob-yellow" },
                        { text: "Panama", template: "template", imageUrl: "images/flags/panama.png" }
                    ]
                },
                {
                    text : "South America",
                    items: [
                        { text: "Argentina", cssClass: "ob-red", spriteCssClass: "ob-flag-argentina"  },
                        { text: "Brazil", imageUrl: "images/flags/brazil.png" },
                        { text: "Chile", cssClass: "ob-green" }
                    ]
                }
            ]
        },
        {
            text   : "Asia",
            enabled: true,
            group  : [
                { text: "Australia" }
            ]
        }
    ])
});

Example using a Kendo UI template in a Menu

This example does the same than default menu behavior but introduces an id for each menu item (if defined, othersie a GUID) and displays the image after the text (instead of before).

<script type="text/kendo-ui" id="template">
    <span class="${data.cssClass}" id="#= data.id || kendo.guid() #">${text}</span>
    # if (data.imageUrl) { #
    <img src="${data.imageUrl}" alt="" class="k-image ob-flag-right">
    # } #
    # if (data.spriteCssClass) { #
    <span class="k-sprite ob-flag-right ${data.spriteCssClass}"></span>
    # } #
</script>

and the result looks like:

KendoUI menu: Using a template how we want each item to look like
KendoUI menu: Using a template how we want each item to look like
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s