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
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
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
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 {
background-image
:
url
(
'http://image.prntscr.com/image/06b1195dd5bf4bcf94fdd5aeda5e20de.png'
);
}
.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
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;
}
})
}
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
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?
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 #" }))
)
)