Can a Grid Column.ClientTemplate be a Kendo ListView?

7 posts, 0 answers
  1. Tim
    Tim avatar
    6 posts
    Member since:
    Dec 2012

    Posted 04 Dec 2012 Link to this post

    Is it possilbe to embed a List View into a Kendo Grid column via a client template?  
    If it's possible how to you bind the List view to the Permmisions list? (Permissions being an IEnumberable<PermissionModel>) 

    @(Html.Kendo().Grid<RoleModel>()
        .Name("RoleGrid")
        .Columns(x =>
                     {
                         x.Bound(p => p.Name).Width(150);
                         x.Bound(p => p.Description).Width(350);
                         x.Bound(p => p.Permissions).ClientTemplate("test");                   
                         
                         x.Command(command =>
                                       {
                                           command.Edit();
                                           command.Destroy();
                                       });
                     }))


    <script type="text/x-kendo-template" id="test" >
        @(Html.Kendo().ListView<PermissionModel>().Name("listView")
                                                                                         .AutoBind(true)
                                                                                         .ToClientTemplate()
                                                                                         )
    </script>
  2. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2196 posts

    Posted 06 Dec 2012 Link to this post

    Hi Tim,

     
    Basically you can use the DataBound event of the Grid to iterate over current Grid rows and initialize ListView from div element that is placed in the client template of the column with current row dataItem for dataSource data. Please check the example below (the EmployeeList contains IEnumerable<Employee>):

    @(Html.Kendo().Grid<ForeignKeyColumnDemo.Models.Order>()
        .Name("Grid")   
        .Columns(columns => {       
            columns.Bound(p => p.OrderID);
            columns.ForeignKey(p => p.EmployeeId, (System.Collections.IEnumerable)ViewData["employees"], "EmployeeId", "Name");
            columns.Bound(p => p.OrderDescription);
            columns.Bound(p => p.OrderDate).Format("{0:d}");
            columns.Bound(p => p.EmployeeList).ClientTemplate("<div class='TreeView'></div>");
        })   
        .Pageable()
        .Sortable()
        .Scrollable()
        .Filterable()
        .Events(e => e.DataBound("onDataBound"))
        .DataSource(dataSource => dataSource       
            .Ajax()     
            .ServerOperation(false)
            .Read(read => read.Action("ForeignKeyColumn_Read", "Home"))
        )
    )
     
    <script type="text/x-kendo-tmpl" id="template">
        <p>
            <h3>Employee name: ${Name}</h3>
            <strong>Employee id:</strong> ${EmployeeId}
        </p>
    </script>
     
    <script>   
        function onDataBound(e) {
            $("#Grid tbody tr .TreeView").each(function () {
                var currentDataItem = $("#Grid").data("kendoGrid").dataItem($(this).closest("tr"));
     
                $(this).kendoListView({
                    dataSource: {
                        data: currentDataItem.EmployeeList
                    },
                    template: kendo.template($("#template").html())
                })
            })
        }
    </script>


    Kind Regards,
    Vladimir Iliev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Tim
    Tim avatar
    6 posts
    Member since:
    Dec 2012

    Posted 06 Dec 2012 Link to this post

    Thanks that works great.  However if the grid is editable: ".Editable(editable => editable.Mode(GridEditMode.PopUp))"

    Then use an edit command to open the pop-up and then click cancel, the List view gets cleared out for the row you were editing.  If you click update, the List view does not clean out. (It will even bring the list view back.  I assume this is because Update causes the databound event to occur.) 

    What event does Cancel cause?
  4. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2196 posts

    Posted 10 Dec 2012 Link to this post

    Hi Tim,

    Basically the Cancel action does not trigger any event and in order to initialize the ListView again you should use the Edit event to bind Click event to the Cancel button. Please check the example below:


    Grid events:

    .Events(e => {
        e.DataBound("onDataBound");
        e.Edit("onEdit");
    })


    Edit event handler:
    function onEdit(e) {
        //replace with your ListView element class name
        var listViewClass = "ListView";
        //Bind click event to the Cancel button
        $(e.container).find(".k-grid-cancel").on("mousedown touchend", function () {
            //get current row UID
            currentRowUID = $(event.srcElement).closest("tr").attr("data-uid");
     
            setTimeout(function () {
                //find the refreshed row
                currentRow = $("[data-uid=" + currentRowUID + "]");
                //get it's dataItem
                currentDataItem = $("#Grid").data("kendoGrid").dataItem(currentRow);
                //initialize the ListView
                currentRow.find("." + listViewClass).kendoListView({
                    dataSource: {
                        data: currentDataItem.EmployeeList
                    },
                    template: kendo.template($("#template").html())
                })
            },100)
        })
    }

    DataBound event handler:
    function onDataBound(e) {
        var listViewClass = "ListView";
     
        $("#Grid tbody tr ." + listViewClass).each(function () {
            var currentDataItem = $("#Grid").data("kendoGrid").dataItem($(this).closest("tr"));
            $(this).kendoListView({
                dataSource: {
                    data: currentDataItem.EmployeeList
                },
                template: kendo.template($("#template").html())
            })
        })
    }


    Kind Regards,
    Vladimir Iliev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  5. Mike
    Mike avatar
    5 posts
    Member since:
    Dec 2012

    Posted 20 Dec 2012 Link to this post

    I implemented this on my Grid, but it looks like the onEdit javascript function is not working correctly.  On 

    currentRowUID = $(event.srcElement).closest("tr").attr("data-uid");
    It finds a srcElement, but it cannot find a "closest" tr, making the currentRowUID undefined.  My full code below:

    @model IEnumerable<ConocoPhillips.CCApprovals.Models.TemplateActivityModel>
     
    @(
     Html.Kendo().Grid(Model).Name("Activities")
        .Columns(columns =>
        {
            //columns.Bound(t => t.Id).Visible(false);
            columns.Bound(t => t.Level).Width("1em").Groupable(false);
            columns.Bound(t => t.Approvers).Groupable(false).Sortable(false).ClientTemplate("<div class='ListView'></div>");
            columns.Bound(t => t.IsInform).ClientTemplate(
                "# if(IsInform == true){ #" + @"Inform Only" +
                "# } else { #" + @"Requires Approval" +
                "#}#").EditorViewData(new { radioDictionary = new Dictionary<String, String>() { { "true", "Inform Only" }, { "false", "Requires Approval" } } }).EditorTemplateName("RadioButtonEditor");
            columns.Bound(t => t.IsMutuallyInclusive).ClientTemplate(
                "# if(IsMutuallyInclusive == true){ #" + @"Requires All Approvers" +
                "# } else { #" + @"Only One Approver Required" +
                "#}#").EditorViewData(new { radioDictionary = new Dictionary<String, String>() { { "true", "Requires All Approvers" }, { "false", "Only One Approver Required" } } }).EditorTemplateName("RadioButtonEditor");
            columns.Command(command => { command.Destroy(); command.Edit(); }).Title("Actions");
        })
        .ToolBar(toolbar => { toolbar.Create(); toolbar.Custom().Text("Refresh").Url("javascript:refreshGrid('Activities')").HtmlAttributes(new { @class = "refreshButton", style = "float: right; height: 30px; width: 30px;" }); })
        .Groupable()
        .Pageable()
        .Sortable()
        .Filterable()
        .Editable(editable => editable.Mode(GridEditMode.PopUp))
        .Events(e =>
        {
            e.DataBound("onDataBound");
            e.Edit("onEdit");
        })
        .DataSource(datasource => datasource
            .Ajax()
            .Model(model =>
            {
                model.Id(t => t.Id);
                model.Field(t => t.Id).Editable(false);
            })
            .Events(events => events.Error("error_handler"))
            //.Sort(c => c.Add("Level").Ascending())
            .Create(create => create.Action("Activities_Create", "Templates"))
            .Read(read => read.Action("Activities_Read", "Templates", new { @templateId = Model.First().TemplateId }))
            .Update(update => update.Action("Activities_Update", "Templates"))
            .Destroy(destroy => destroy.Action("Activities_Destroy", "Templates"))
        )
    )
    <script type="text/x-kendo-tmpl" id="template">
        <p>
            <h3>Name: ${Name}</h3>
            <strong>Id:</strong> ${UserID}
        </p>
    </script>
    <script type="text/javascript">
        function error_handler(e) {
            if (e.errors) {
                var message = "Errors:\n";
                $.each(e.errors, function (key, value) {
                    if ('errors' in value) {
                        $.each(value.errors, function () {
                            message += this + "\n";
                        });
                    }
                });
                alert(message);
            }
        }
     
        function onEdit(e) {
            //replace with your ListView element class name
            var listViewClass = "ListView";
            //Bind click event to the Cancel button
            $(e.container).find(".k-grid-cancel").on("mousedown touchend", function () {
                //get current row UID
                currentRowUID = $(event.srcElement).closest("tr").attr("data-uid");
     
                setTimeout(function () {
                    //find the refreshed row
                    currentRow = $("[data-uid=" + currentRowUID + "]");
                    //get it's dataItem
                    currentDataItem = $("#Activities").data("kendoGrid").dataItem(currentRow);
                    //initialize the ListView
                    currentRow.find("." + listViewClass).kendoListView({
                        dataSource: {
                            data: currentDataItem.Approvers
                        },
                        template: kendo.template($("#template").html())
                    });
                }, 100);
            });
     
            kendoize();
        }
     
        function onDataBound(e) {
            var listViewClass = "ListView";
     
            $("#Activities tbody tr ." + listViewClass).each(function () {
                var currentDataItem = $("#Activities").data("kendoGrid").dataItem($(this).closest("tr"));
                $(this).kendoListView({
                    dataSource: {
                        data: currentDataItem.Approvers
                    },
                    template: kendo.template($("#template").html())
                });
            });
     
            kendoize();
        }
    </script>
    (Ignore the kendoize method call).  Any help?
  6. Tim
    Tim avatar
    6 posts
    Member since:
    Dec 2012

    Posted 20 Dec 2012 Link to this post

    Hi Mike,
     I had the same problem.

    I found the X "close" button and the cancel button both have different sources.  Because of this I ended up making an event for each.

    I would just use Chrome/Firebug too and insert a debugger; call in the function.  Then find $(event.srcElement) on the page and figure what navigation you need to do manually, while in debugger. 

    $(e.container).find(".k-grid-cancel").on("mousedown touchend", function () {               
     //get current row UID                
    currentRowUID = $(event.srcElement).closest("div").parent().attr('data-uid');
    $(e.container).parent().find(
    '.k-i-close').on("mousedown touchend", function () {                
    //get current row UID                
    currentRowUID = $(event.srcElement).parent().parent().parent().parent().find('.k-window-content').attr('data-uid');
  7. Mike
    Mike avatar
    5 posts
    Member since:
    Dec 2012

    Posted 20 Dec 2012 Link to this post

    Lucky for me, your exact navigation worked for my grid too!  Thanks a bunch!
Back to Top