This is a migrated thread and some comments may be shown as answers.

External ClientTemplate, access row or dataItem in javascript function call

10 Answers 2468 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Gregory
Top achievements
Rank 1
Gregory asked on 07 Mar 2017, 04:42 PM

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)
)
 
}

10 Answers, 1 is accepted

Sort by
0
Alex Hajigeorgieva
Telerik team
answered on 09 Mar 2017, 10:17 AM
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 (charts) and form elements.
0
Gregory
Top achievements
Rank 1
answered on 09 Mar 2017, 01:40 PM
Thank you Alex, that worked exactly how we needed it to.
0
Gregory
Top achievements
Rank 1
answered on 09 Mar 2017, 09:51 PM
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.
0
Alex Hajigeorgieva
Telerik team
answered on 13 Mar 2017, 12:24 PM
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 (charts) and form elements.
0
Gregory
Top achievements
Rank 1
answered on 13 Mar 2017, 04:15 PM
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.
0
Alex Hajigeorgieva
Telerik team
answered on 15 Mar 2017, 10:21 AM
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.
0
Gregory
Top achievements
Rank 1
answered on 15 Mar 2017, 02:59 PM

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;
        }
    })
}
0
Accepted
Alex Hajigeorgieva
Telerik team
answered on 17 Mar 2017, 03:28 PM
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 (charts) and form elements.
0
Gregory
Top achievements
Rank 1
answered on 20 Mar 2017, 06:29 PM

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?

0
Gregory
Top achievements
Rank 1
answered on 21 Mar 2017, 03:35 PM

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 #" }))
        )
)
Tags
Grid
Asked by
Gregory
Top achievements
Rank 1
Answers by
Alex Hajigeorgieva
Telerik team
Gregory
Top achievements
Rank 1
Share this question
or