External ClientTemplate, access row or dataItem in javascript function call

11 posts, 1 answers
  1. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 07 Mar 2017 Link to this post

    I am using an External ClientTemplate to display some information.  I have created a link out of one of my data values and upon click, I would like to show additional information.  I have this working using the Custom Command action, but the button takes up too much real-estate, hence the new link.  What I cannot figure out is how to perform the same javascript call to accomplish what is working from the Custom Command.

    My javascript that works for the Custom Command.

    var detailsTemplate = kendo.template($("#statusTemplate").html());
     
    function showStatusDetails(e) {
        e.preventDefault();
     
        var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
        var wnd = $("#Details").data("kendoWindow");
     
        wnd.content(detailsTemplate(dataItem));
        wnd.center().open();
    }

     

    My External ClientTemplate.  Looking for what to replace the ????? with.

    <script type="text/x-kendo-template" id="statusRowTemplate">
        <div id="statusContainer">
            <a href="\\#" onclick='showStatusDetails(??????)'><h4 style="height:10px;">#= Description # (#= Code #) </h4></a>
            <div class="dataRow">
                <div class="dataRowField">
                    Status Date/Time:
                </div>
                <div class="dataRowValue">
                    #= FormattedStatusDateTime #
                </div>
            </div>
            <div class="dataRow">
                <div class="dataRowField">
                    Entered By:
                </div>
                <div class="dataRowValue">
                    #= EnteredByName #
                </div>
            </div>
        </div>
    </script>

     

    My grid and window markup

    @(Html.Kendo().Grid<Status>()
            .Name("StatusGrid")
            .Columns(columns =>
            {
                columns.Bound(s => s.Code).Title("Status Information").ClientTemplate("#=statusRowTemplate(data)#").HtmlAttributes("style='padding:0px'");
                columns.Command(command =>
                {
                    command.Custom("View").Click("showStatusDetails");
                    command.Destroy().Text("Delete");
                }).Width(175);
            })
            .DataSource(ds =>
                ds.Ajax()
                .Model(model => model.Id(s => s.StatusID))
                .ServerOperation(false)
                .Read(r => r.Action("ReadStatuses", "ActionPages"))
                .Destroy(destroy => destroy.Action("DeleteStatus", "ActionPages", new { StatusID = "#= Id #" }))
            )
            .Events(e => e.DataBound("dataBound"))
    )
     
    @(Html.Kendo().Window().Name("Details")
        .Title("Status Details")
        .Visible(false)
        .Modal(true)
        .Draggable(true)
        .Width(500)
    )
     
    }
  2. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    1081 posts

    Posted 09 Mar 2017 Link to this post

    Hello Gregory,

    One way I can think of to achieve the required functionality is to pass this in the showStatusDetails function.

    <a href="\\#" onclick='showStatusDetails(this)'><h4 style="height:10px;">#= Description # (#= Code #) </h4></a>

    This means that the function itself will need a minor modification since we will be passing the raw HTML element. I believe that it should work correctly when modified as below:

    var detailsTemplate = kendo.template($("#statusTemplate").html());
      
    function showStatusDetails(e) {
     var grid = $("#StatusGrid").data("kendoGrid");
     var dataItem = grid.dataItem($(e).closest("tr")); // 'e' is the HTML element <a>
     var wnd = $("#Details").data("kendoWindow");
      
     wnd.content(detailsTemplate(dataItem));
     wnd.center().open();
    }

    Kind Regards,
    Alex Hajigeorgieva
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 09 Mar 2017 in reply to Alex Hajigeorgieva Link to this post

    Thank you Alex, that worked exactly how we needed it to.
  4. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 09 Mar 2017 in reply to Alex Hajigeorgieva Link to this post

    Hello Alex.  As a follow up, I also need to execute the delete command from within the template.  Ideally, I'd like to hyperlink a graphic and have it execute from the onclick of that, but I am open to other methods if necessary.
  5. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    1081 posts

    Posted 13 Mar 2017 Link to this post

    Hi Gregory,

    I am glad to hear that the original question is resolved as desired.

    The additional required functionality of deleting a dataItem via a click on an image button from the external template can be achieved with a standard JavaScript approach along with the Kendo UI Data Source methods remove() and sync().

    remove API: http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#methods-remove
    sync API: http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#methods-sync

    - Extend the client template to include the button with an image - e.g:

    <input id="delete-image-btn" type="image" src="http://d585tldpucybw.cloudfront.net/sfimages/default-source/labs/kendo/kendoui-angular2/kendoka.png?sfvrsn=4" width="50" height="50">

    - Attach an event handler in the showStatusDetails function:

    var detailsTemplate = kendo.template($("#statusTemplate").html());
       
    function showStatusDetails(e) {
     var grid = $("#StatusGrid").data("kendoGrid");
     var dataItem = grid.dataItem($(e).closest("tr")); // 'e' is the HTML element <a>
     var wnd = $("#Details").data("kendoWindow");
       
     wnd.content(detailsTemplate(dataItem));
     wnd.center().open();
     
     // the handler when the image button is clicked
     $("#Details").on("click", "#delete-image-btn", function (e) {
       grid.dataSource.remove(dataItem);
       grid.dataSource.sync();
       wnd.close();
      })
    }

    Kind Regards,
    Alex Hajigeorgieva
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  6. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 13 Mar 2017 in reply to Alex Hajigeorgieva Link to this post

    Thank you Alex, that is helpful.  However, I am not deleting the item from the popup detail window.  The button / image will be in the row's template.
  7. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    1081 posts

    Posted 15 Mar 2017 Link to this post

    Hi Gregory,

    I apologise, I must have misunderstood which template you are referring to:
     
    I also need to execute the delete command from within the template. Ideally, I'd like to hyperlink a graphic and have it execute from the onclick of that, but I am open to other methods if necessary.

    If you wish to use the approach with the background image, you could use the below CSS rules:

    .k-grid-delete, .k-grid-delete:hover {
    }
    .k-i-close {
     visibility: hidden;
    }

    Here is the result from the above:
    http://dojo.telerik.com/AwOGE

    Taking this approach will rid you of the necessity to attach click handlers to custom buttons. Alternatively, you could use the approach for the command column and template in the same way as discussed in our earlier communication of this thread, except instead of displaying the dataItem in the window, you would call the remove() method.

    Have you thought of using some of the icons which are available in the Kendo UI web font icons?

    http://docs.telerik.com/kendo-ui/styles-and-layout/icons-web#web-font-icons

    Regards,
    Alex Hajigeorgieva
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  8. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 15 Mar 2017 in reply to Alex Hajigeorgieva Link to this post

    Thank you Alex.  

    I apologize in advance for some lack of knowledge here, I am new to MVC coming from Web Forms.

    If you take a look at my original post, I am using a client template for my entire row.  This format is required from my design team.  I have added a delete button to that template and I am trying to do 2 things: execute the remove/delete functionality and hide the button under certain conditions.

    Here is the modified version of my template for the row.

    <script type="text/x-kendo-template" id="statusRowTemplate">
        <div id="statusContainer">
            <div class="actions">
                <input id=".delete-image-btn" type="button" value="Delete" />
            </div>
     
            <a href="\\#" onclick="showStatusDetails(this)"><h4 style="height:10px;">#= Description # (#= Code #) </h4></a>
            <div class="dataRow">
                <div class="dataRowField">
                    Status Date/Time:
                </div>
                <div class="dataRowValue">
                    #= FormattedStatusDateTime #
                </div>
            </div>
            <div class="dataRow">
                <div class="dataRowField">
                    Entered By:
                </div>
                <div class="dataRowValue">
                    #= EnteredByName #
                </div>
            </div>
        </div>
    </script>

     

    I am attempting to locate the button in the dataBound event per some examples I have come across online, but it does not seem to find the button itself, but the row where the button exists...

    var statusRowTemplate = kendo.template($("#statusRowTemplate").html());

    function dataBound(e) {
        var grid = this;
        grid.tbody.find("tr[role='row']").each(function (e) {
            var aryUndeletable = ["POD", "PODP", "PODWC"];
            var model = grid.dataItem(this);
     
            if (($.inArray(model.Code, aryUndeletable) > 0) || (model.CreatedElectronically == 'Y') || (model.ClosedSts == 'Y')) {
                var delButton = $(this).find(".delete-image-btn");
                debugger;
                delButton.hide();
                debugger;
            }
        })
    }
  9. Answer
    Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    1081 posts

    Posted 17 Mar 2017 Link to this post

    Hi Gregory,

    Thank you very much for the clarification.

    Here is how to achieve both functionalities:

    1) Execute the remove/delete functionality. I have a couple of notes for you here:

    - get the Kendo UI Grid instance in a $(document).ready() and use it for the other handlers. If the current implementation is executed on dataBound, this means that the handlers are attached every time there is paging, editing, grouping etc.

    - if an id of the <input>(the image button) is needed, make sure it is a unique one, e.g. the dataItem id:
    <input id="#=ProductID#" class="delete-btn" type="button" value="Delete" />

    <script type="text/javascript">
     
     var rowTemplate = kendo.template($("#rowTemplate").html());
     var detailsTemplate = kendo.template($("#detailsTemplate").html());
     var grid;
     
     $(document).ready(function () {
      grid = $("#grid").data("kendoGrid");
      $("#grid").on("click", ".delete-btn", function (e) {
        var dataItem = grid.dataItem($(e.target).closest("tr"));//'e.target' is the <input/>
        grid.dataSource.remove(dataItem);
       grid.dataSource.sync();
      })
     });
     
    function showStatusDetails(e) {
       var dataItem = grid.dataItem($(e).closest("tr")); // 'e' is the HTML element <a>
       var wnd = $("#Details").data("kendoWindow");
       wnd.content(detailsTemplate(dataItem));
       wnd.center().open();
    }
    </script>


    2) Conditionally hide a button in the template

    For this scenario, you can place plain JavaScript in the template wrapping each code row with hashtags, e.g:

    <div class="actions">
     # if(ProductName === "Chai") { #
     <input id="#=ProductID#" class="delete-btn" type="button" value="Delete" />
     # } #
    </div>

    The code above will only render the button if the ProductName of the dataItem is "Chai".

    Here is more information on the Kendo UI Templates syntax:

    http://docs.telerik.com/kendo-ui/framework/templates/overview#templates-overview

    Kind Regards,
    Alex Hajigeorgieva
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  10. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 20 Mar 2017 in reply to Alex Hajigeorgieva Link to this post

    Golden!  Thank you, both those solutions worked after some tweaking.

    $(document).ready(function () {
        $("#StatusGrid").on("click", ".delete-image-btn", function (e) {
            var grid = $("#StatusGrid").data("kendoGrid");
            var dataItem = grid.dataItem($(e.target).closest("tr"));
            grid.dataSource.remove(dataItem);
            grid.dataSource.sync();
        })
    });

     

    # if (IsDeletable == true) { #
    <div class="actions">
        <input id="\#= StatusId \#" class="delete-image-btn" type="button" value="Delete" />
    </div>
    # } #

     

    Last question.  How do we call server-side code to actually perform the delete against the database?

  11. Gregory
    Gregory avatar
    9 posts
    Member since:
    Dec 2014

    Posted 21 Mar 2017 in reply to Gregory Link to this post

    Disregard my last question.  I see that calling the remove and sync function invokes the server side function defined in the Destroy declaration on the grid.

    @(Html.Kendo().Grid<Status>()
            .Name("StatusGrid")
            .Columns(columns =>
            {
                columns.Bound(s => s.Code).Title("Status Information").ClientTemplate("#=statusRowTemplate(data)#").HtmlAttributes("style='padding:0px'");
            })
            .DataSource(ds =>
                ds.Ajax()
                .Model(model => model.Id(s => s.StatusID))
                .ServerOperation(false)
                .Read(r => r.Action("ReadStatuses", "ActionPages"))
                .Destroy(destroy => destroy.Action("DeleteStatus", "ActionPages", new { StatusID = "#= Id #" }))
            )
    )
Back to Top