How to scroll the detail row of a Kendo Grid into view on select

I decided I liked the idea of only having one detail pane at a time in my web grid. It gets too cluttered having a number of them open. I got feedback from my users that when selecting a row towards the end of the screen, they had to then scroll to see all the details.

I did a simply time cost analysis and instead of changing the UI to show the data in a popup, it was faster and cheaper just to scroll down the page. Simple, eh.

Here is the script to do a scroll when a row is selected in the Kendo Grid to ensure the detail pane is visible.

  function engagementRowSelected(e) {

            var eventTarget = (event.target) ? $(event.target) : $(event.srcElement);

            var grid = $("#engagementsContainer").data("kendoGrid");
            var gridSource = grid.dataSource;
            var selectedRow = this.select()[0];

            var position = $(selectedRow).position();
            $(window).scrollTop(position.top);

        }

I left out all the code that does the selection, and forcing to display only one row at a time. If that is something people want to see or use, I can post that as a simple demo later.

Happy coding!

Kendo UI Chart Legend Overlaps with the Plot area and the pie numbers

I kept running into an issue where the chart kept drawing over itself. Basically, the chart would draw the lines and numbers that extend from the pie area and overlap the legend at the bottom. It did it when I had it on the right as well. This is stupid, and stupid I had to use a workaround, but here is the workaround.

My style. Edit as you need for yours.

        .chart-wrapper, .chart-wrapper .k-chart
        {
            height: 300px;
            width: 325px;
            margin-bottom: 20px;
        }

The code I had to add to my chart create:

 $(phaseContainerId).kendoChart({
                title: {
                    position: "bottom",
                    visible: false

                },
                legend: {
                    visible: true,
                    offsetX: -0,
                    offsetY: 20,
                    position: 'bottom'
                }
                ,........

I also added the following to avoid clipping, which can happen.

 chartArea: {
                    background: "",
                    margin: { top: 30, left: 5, right: 5, bottom: 15 }, padding: { top: 10, left: 10, right: 10, bottom: 10 }
                },

Notice the offset. That moves the legend around. You may need to play with the numbers depending on your font and other design choices.

Happy coding!

Fix: Kendo Grid Template gives error “Unable to get value of the property ‘replace’: object is null or undefined”

I got the lovely unhelpful error “Unable to get value of the property ‘replace’: object is null or undefined” from the Kendo Grid when I added a template to a column. This was a completely useless error that led me to staring at the javascript stack and walking through the minified code. Which, by the way, is very painful to look through obfuscated minified code.

After entirely too long analyzing the code, I finally figured out the root cause. I had an ever so small typo in my template retrieval declaration and it was returning back a null template. Why on earth didn’t the Telerik guys NULL check this and fire a friendly error? All of two lines of code would have saved me some trouble.

See, javascript is entirely too friendly to typing mistakes.

Here is the errant code:

    {
                             title: "Planning", width: "100px",                                       
                             template: kendo.template($("myPortfolio_PlanningTemplate").html())
                         },

Here is the fixed code.

    {
                             title: "Planning", width: "100px",                                       
                             template: kendo.template($("#myPortfolio_PlanningTemplate").html())
                         },

Painful lesson in remember to put in the hashtag for ID lookups. Easy to forget when in a hurry.

Happy Coding!

How to add complex headers to a Kendo grid using simple jQuery javascript

I was trolling through the horrible documentation provided by Telerik for the kendo grid. I needed to create a complex header. Basically, a two row header so that I could group columns in a visually meaningful way.

simple example:

I spent far too much time reading how it couldn’t be done. A light bulb finally hit me, this is html. Yeah, flexibility abounds if you can be clever. I simply opened up the old browser developer tool and looked at the generated html for the grid.I then realized, this is a simple table, why not just inject another table row.

So, here is the easy way to add another row to your kendo grid and make a nice complex header. You can use this technique to go to town on adding additional features to your grid as well.

//create grid.

function BuildMyActionsList(tasks) {
            var list = $("#tasksContainer");
            list.empty();

            list.kendoGrid(
                {
                    dataSource: {
                        data: tasks,
                        schema: {
                            model: {
                                id: "Id",
                                fields: {
                                    Name: { type: "string" },                                    
                                    LessThanEGAs: { type: "number" },
                                    GreaterThanEGAs: { type: "number" },
                                    LessThanRisks: { type: "number" },
                                    GreaterThanRisks: { type: "number" },
                                    LessThanCNs: { type: "number" },
                                    GreaterThanCNs: { type: "number" },                                    
                                    ReportSignDate: { type: "date" }
                                }
                            }
                        },
                        //     pageSize: 20
                    },
                    dataBound: addExtraStylingToTasksGrid,
                    filterable: true,
                    scrollable: true,
                    sortable: true,
                    columns: [
                        {
                            field: "Name", title: "Engagement", width: "175px",
                            filterable: {
                                extra: false,
                                operators: {
                                    strings: {
                                        startswith: "Starts with",
                                        eq: "Is equal to",
                                        neq: "Is not equal to"
                                    }
                                }
                            }
                        },                        
                        {
                            field: "LessThanEGAs", title: "EGA's", width: "80px"
                        },
                        {
                            field: "GreaterThanEGAs", title: "CN's", width: "80px"
                        },
                        {
                            field: "LessThanRisks", title: "Risk's", width: "80px"
                        },
                        {
                            field: "GreaterThanRisks", title: "EGA's", width: "80px"
                        },
                        {
                            field: "LessThanCNs", title: "CN's", width: "80px"
                        },
                        {
                            field: "GreaterThanCNs", title: "Risk's", width: "80px"
                        },
                        {
                            field: "ReportSignDate", title: "Report Signing", width: "125px", filterable: false                            
                        }
                    ]
                });

            list.find("thead").first().prepend("<tr><th></th><th class='lessThanDaysGrouping' colspan='3'>&lt;= 2 Days</th><th  class='greaterThanDaysGrouping' colspan='3'>&gt; 7 Days</th><th></th></tr>");

        }

Notice , the line at the end. This is where we search the table for the header and then prepend the row. Just make sure your new row definition aligns with the same column structure as your table. If you need help with this, search on html tables on google.

Line of code that does the magic:

  list.find("thead").first().prepend("<tr><th></th><th class='lessThanDaysGrouping' colspan='3'>&lt;= 2 Days</th><th  class='greaterThanDaysGrouping' colspan='3'>&gt; 7 Days</th><th></th></tr>");

 

Happy Coding!

 

Click event bug with the iPad when using jQuery

I am writing a web application that uses a kendo grid with a detail pane. I hooked up a click event on a table in the detail pane to navigate to another page. It worked beautifully on the desktop. I tested on the iPad, and when you clicked a row, it would immediately fire off the click event and navigate away. WTF.

This drove me nuts. I found a person that also had a click issue posting about their oddity. Slightly different for them, but the fix is the one and the same.

It turns out that on the iPad, you can bind to the touchevent event instead of the click event and the problem goes away. It also takes out the 300ms delay some complain about.

Implementation is rather easy. Instead of using .click(function….) use bind.

Put this at the top of your script section.

  var ua = navigator.userAgent,
            clickEventBindingName = (ua.match(/iPad/i)) ? "touchstart" : "click";//stupid ipad workaround

Now, in your code, you simply using this to capture the events.

  $("#YOURELEMENT").bind(clickEventBindingName,
                function () {
                    doStuff();
                }
                );

Problem solved.

 

Happy Coding.

 

How to display a complex type/list in a Kendo UI Grid client side using a simple template

I had the need to display multiple values from a list that was attached to each row. Simply put, I had a list of Roles the user could be in for each record. I wanted to display them delimited. Turns out, not that hard.

I at first was not loving the idea of using the Telerik kendo grid. I preferred to roll my own html using javascript alone. Since this is a large team based project, I decided to use a more consistent approach and utilize the Kendo library. Painful at first, since the documentation sucks more than an industrial vacuum.

The beauty lies in the power of the template. Telerik is nice enough to let you use powerful javascript in the templates, which makes it wonderful to configure and tailor each cell to your specifications. For this post, the need was to write a pipe delimited list to the cell of all the role names.

Here is the magic. The template I created. You obviously need to tailor for your field names.

    <script id="rolesColumnTemplate" type="text/x-kendo-tmpl">    

        # for(var iRoleIndex=0;iRoleIndex< Roles.length;iRoleIndex++){ #
        # if(iRoleIndex==0){  #
        #: Roles[iRoleIndex].Name #
        # } else { #
        #: " | " + Roles[iRoleIndex].Name #
        # } } #
    </script>

You need to bind it to a column which is also easy.

  columns: [

                        {
                            field: "Roles", title: "Roles", width: "80px",
                            template: kendo.template($("#rolesColumnTemplate").html()),
                            filterable:
                                {
                                    operators: {
                                        string: {
                                            eq: "Is equal to",
                                            neq: "Is not equal to"
                                        }
                                    }
                                }
                        }
                    ]

Notice how easy that was. Well, easy once you know it.  Not easy if you had to figure it out on your lonesome.

Happy Coding!