Readable Kendo UI Grid Column Templates with the Razor engine

Everybody needing to use Kendo UI web controls from the Telerik will earlier or later have to do something with templating.
The examples on their site among the Web Demos were not so attracting for me so I decided to work out a “cleaner” way.

One could do it by concatenating strings (that’s the approach which I most dislike):

@(Html.Kendo().Grid(Model.Items)
    .Columns(c =>
        {
            c.Bound(p => p.Id).Visible(false);
            c.Template(e => { }).Title("Templated Column").ClientTemplate("<div class='employee-details'>" +
                        "<ul>" +
                            "<li><label>Country:</label>#= Country #</li>" +
                            "<li><label>City:</label>#= City #</li>" +
                            "<li><label>Address:</label>#= Address #</li>" +
                            "<li><label>Home Phone:</label>#= HomePhone #</li>" +
                        "</ul>" +
                    "</div>");
        })
)

The next opportunity when creating a listview is to use client template id, which is containing not so readable, and by Visual Studio not syntax highlighted HTML code:

<script type="text/x-kendo-tmpl" id="template">
    <div class="span3">
        <ul>
            # $.each(Persons, function( index, value ) {#
            <li>
                #: value.Name # 
            </li>
            # }) #
        </ul>
    </div>
</script>

Well this is slightly more readable but has the disadvantage of having the property names of the bound objects as a simple string – making it extremely error prone. If your view model changes, you have to change also your template script without design time support.

The next approach is much more attractive by using a Razor helper in the cshtml file as follows:

@helper DescriptionTemplate()
{
    <div class="span3">
        <ul>
            # $.each(Persons, function( index, value ) {#
            <li>
                #: value.Name # 
            </li>
            # }) #
        </ul>
    </div>
}

Here we got a syntax highlight for HTML but still have the problem of the view model properties. My solution for that was to create an HTML helper as follows:

public static MvcHtmlString PropertyName<TModel>(this HtmlHelper html, Expression<Func<TModel, object>> propertyExpression)
{
    string propertyName = null;
    if (propertyExpression.Body is UnaryExpression)
    {
        var body = (UnaryExpression)propertyExpression.Body;
        propertyName = ((MemberExpression)body.Operand).Member.Name;
    }
    else if (propertyExpression.Body is MemberExpression)
    {
        var body = (MemberExpression)propertyExpression.Body;
        propertyName = body.Member.Name;
    }

    return MvcHtmlString.Create(propertyName);
}

And then the end usage is:

@helper DescriptionTemplate()
{
    <div class="span3">
        <ul>
            # $.each(@Html.PropertyName((ItemViewModel o) => o.Persons), function( index, value ) {#
            <li>
                #: value.@Html.PropertyName((PersonViewModel o) => o.Name) # 
            </li>
            # }) #
        </ul>
    </div>
}

@(Html.Kendo().Grid(Model.Items)
  .Columns(c =>
    {
        c.Bound(p => p.Id).Visible(false);
        c.Template(e => { }).Title("SomeColumn").ClientTemplate(DescriptionTemplate().ToHtmlString()).Width(250);
    })
)    

You also have to compile views for your MVC projects which is described e.g.: here.

That’s it. It is still not beautiful – I know. It is however much more readable and less error prone by having the PropertyName helper method and at least the HTML is highlighted. Have fun using this technique.

Advertisements

About Tamas Nemeth

Husband and proud father of two daughters in Nürnberg. I'm working as a Senior Software Developer and an enthusiastic Clean-Coder. I spend most of my free time with my family (playing, hiking, etc...). I also play table-tennis and badminton sometimes...
This entry was posted in Technical Interest and tagged , , , , , , . Bookmark the permalink.

6 Responses to Readable Kendo UI Grid Column Templates with the Razor engine

  1. satarinho says:

    That is working really nice. Just one question, what if you want to put an if condition if the template to render some content depending on a model property? I tried it but it doesn’t work.

  2. Tamas Nemeth says:

    Hallo satarinho,
    How exactly do you image it to work?
    I would probably use the “?” operator as follows:
    c.Template(e => { }).Title(“SomeColumn”).ClientTemplate(Model.BoolProperty?DescriptionTemplate().ToHtmlString():OtherTemplate().ToHtmlString()).Width(250);
    Or something like that.
    I hope I could help you with this one…

    • satarinho says:

      Hi, my code is this:
      columns.Template(model => model.ManagerId).ClientTemplate(
      “#= ManagerKindDesc #”
      + “#if (!IsActive) { #BORRADO# } #”
      + “\\##= ManagerId #
      + “#= ManagerName #”).Title(“Mánager”);

      As you can see I am trying to display a div when the Model property IsActive is set to false. This approach works good, but when I try to put the template in a helper it gives an error. When there is no “if” condition it works perfect.
      Maybe I will use your approach to avoid using the template directly on the Kendo widget configuration.

  3. Tamas Nemeth says:

    Are you certain that the IsActive property is available on the client side? Write out its value for a test. After that you should be able to make conditions on it.

  4. Rajeev says:

    Hello Thomas,
    Thanks for the article.It is working really good for data.
    Do you have anything for configuring the each cell header?
    Eg : Header portion

    AA/ BBB

     
    AAAA / BBB / CCC

    AA ALERT
    etc
    etc

    Thank you in advance
    Rajeev Kalamthodi

  5. Rajeev says:

    Hello Thomas,
    I have copied some html tags. Unfortunately it is not appearing here. There are td’s and tr’s for my header.
    Rajeev

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