Custom row/checkbox template for Kendo UI grid - razor

I am trying to create a custom row template for a Kendo UI grid that includes the checkbox functionality. I have the grid created like this:
#(Html.Kendo().Grid(Model.Users)
.Name("usersGrid")
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(c => c.UserName);
})
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false))
.ClientRowTemplate(UsersClientTemplate))
With a function to generate the row template like this:
Func<Grid<User>, string> UsersClientTemplate = (grid) =>
{
var id = Guid.NewGuid();
return #"<tr data-uid='#:uid#' role='row'>" +
"<td role='gridcell'>" +
$"<input class='k-checkbox' data-role='checkbox' type='checkbox' id={id}>" +
$"<label class='k-checkbox-label k-no-text' for={id}>​</label>" +
"</td>" +
"<td role='gridcell'>" +
"<a href='/users/details/#:data.Id#'>#:data.UserName#</a>" +
"</td>" +
"</tr>";
};
The problem is I can't figure out how to generate the unique ids for each row's template. If I don't include the id attribute on the checkbox input element and the for attribute on the checkbox label element, the checkbox/row selection doesn't work. But with the function I have above, the same id is generated for every row template and then the checkbox/row selection only works for the first row, obviously.
What is a better way to do this?

Templates are generated when the grid is built so as you have seen the id is always the same. What you want is to databind so kendo replaces the id with each record. I use my entity key with a prefix like "cb_" for checkbox:
$"<input class='k-checkbox' data-role='checkbox' type='checkbox' id='cb_#:uid#'>" +
$"<label class='k-checkbox-label k-no-text' for='cb_#:uid#'>​</label>" +

Related

Kendo grid not displaying Clolumns data that are not include in client templete row

My Isuue is,I have added kendo grid and bounded with data getting from a particular class. Then, I appended with one more column includes icons by using client row templete.
corresponding data is not displaying after I appended with one more column(client row templete.before its working absolutely fine). I need to show data in all columns.
I tried to include but failed.
My Code is-
#(Html.Kendo().Grid
(Model.Services)
.Name("SummaryGrid")
.Columns(columns =>
{
columns.Bound(c => c.Service_Name).Title("Service Name");
columns.Bound(c => c.Service_Type).Title("Service Type");
columns.Bound(c => c.Service_Resource).Title("Resource");
columns.Bound(c => c.Region).Title("Region");
columns.Bound(c => c.TotalQuantity).Title("Quantity");
columns.Bound(c => c.UnitOfMeasure).Title("Unit of Measure");
columns.Bound(c => c.TotalCost).Title("Total Cost($)");
columns.Template(e => { }).ClientTemplate(" ").Title("Actions");
})
.ClientRowTemplate(
" <td >" +
"<a href='javascript:void(0);' title='Edit' class='clsEditService'> <span class='icon-E70F blackIcon'></span></a>" + " </a>"+
"<a href='javascript:void(0);' title='Delete' class='clsDeleteService'>"+
"<span class='icon-E74D blackIcon'></span>"+" </a>"+
" </td>"
)
Expected grid to show all columns corresponding data at the end edit and delete icons as well(I am not looking for default edit and delete functionalities from kendo)
A ClientRowTemplate adds a row below your grid row. If you want a column for your edit/delete, try something like this:
columns.Template(e => {}).Title("Actions")
.ClientTemplate("#<a title='Edit' class='clsEditService'><span class='k-grid-edit icon-E70F blackIcon'></span></a> " +
"<a title='Delete' class='clsDeleteService'><span class='k-grid-delete icon-E74D blackIcon'></span></a>");
Note that if you add the classes k-grid-edit and k-grid-delete this will tell kendo to run your update and delete Ajax actions automatically, otherwise set your own events accordingly.

ClientTemplate expression to include javascript conditional

Have been using Kendo UI MVC for a while now and need to put some conditional logic on a checkbox that is in one field of the grid.
The fields in the grid that need to be evaluated are
Going off the example here
https://docs.telerik.com/aspnet-mvc/helpers/grid/faq#how-to-display-checkboxes-in-ajax-bound-grids
columns.Bound(p => p.ProductName).ClientTemplate(
"# if (HasIcon == true) { #" +
"<img src='" + Url.Content("~/Content/icons/") + "#= ProductID #.png' alt='#= ProductName # icon' />" +
"# } else { #" +
"#: ProductName #" +
"# } #"
);
How do I format the test within the conditional to use a grid field value ?
eg testing if ProductID is a specific value like this?
columns.Bound(p => p.ProductName).ClientTemplate(
"# if (#= ProductID # == 123) { #" +
"<img src='" + Url.Content("~/Content/icons/") + "#= ProductID #.png' alt='#= ProductName # icon' />" +
"# } else { #" +
"#: ProductName #" +
"# } #"
);
due to the sometimes complex nature of client templates, I personally tend to use the javascript function method
columns.Bound(p => p.ProductName).ClientTemplate("#= getProductIcon(data,
Url.Content("~/Content/icons/")#);
then in a js script block
function getProductIcon(data, imgUrl) {
if (data.ProductID == 123)
return "<img src='" + imgUrl + data.ProductID + ".png' alt='" + data.ProductName + " icon' />";
else
return data.ProductName;
}
just make sure your script is loaded before the grid is instantiated otherwise you'll run into getProductIcon undefined or some similar error. Also it's easier to throw a debugger on your javascript function and really see what's going on and verify the data in/out.
Excuse any typos in the above, I'm not at a location where I can validate the razor syntax at the moment.

Customize html output for a field's droplist options

I have a field called icon, which is a droplist sourced from folder in the content tree. I would like the list to not just show the text value(shown in the screen shot) but also to utilize an icon font and display what the actual icon would look like. Basically customizing the content editor's droplist for this field from:
<option value="gears">gears</option>
to
<option value="gears">gears <span class="my-icon-font-gears"></span></option>
Is there any documentation on how to modify the outputted html for a droplist, and to modify the content editor page to load another link, in this case a font-file.
I created a module on the marketplace that does something similar. You can have a look here. There is some documentation on there explaining how to use it.
The code is also on Git if you want to have a look.
Suggest you use the Droplink field type instead of the Droplist, since the value is stored by GUID and this will lead to less longer term problems if the link item is renamed or moved. In any case you need a custom field, inherit from Sitecore.Shell.Applications.ContentEditor.LookupEx (which is the DropLink field type) and override the DoRender() method with the custom markup you require.
It's not possible to embed a span tag since the option tag cannot contain other tags as it is invalid HTML. Adding it will cause the browser to strip it out. You can however set the class on the option itself and style that.
`<option value="gears" style="my-icon-font-gears">gears</option>`
Here is some sample code to achieve the field.
using System;
using System.Web.UI;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Globalization;
namespace MyProject.CMS.Custom.Controls
{
public class StyledLookupEx : Sitecore.Shell.Applications.ContentEditor.LookupEx
{
private string _styleClassField;
private string StyleClassField
{
get
{
if (String.IsNullOrEmpty(_styleClassField))
_styleClassField = StringUtil.ExtractParameter("StyleClassField", this.Source).Trim();
return _styleClassField;
}
}
// This method is copied pasted from the base class apart from thhe single lined marked below
protected override void DoRender(HtmlTextWriter output)
{
Assert.ArgumentNotNull(output, "output");
Item[] items = this.GetItems(Sitecore.Context.ContentDatabase.GetItem(this.ItemID, Language.Parse(this.ItemLanguage)));
output.Write("<select" + this.GetControlAttributes() + ">");
output.Write("<option value=\"\"></option>");
bool flag1 = false;
foreach (Item obj in items)
{
string itemHeader = this.GetItemHeader(obj);
bool flag2 = this.IsSelected(obj);
if (flag2)
flag1 = true;
/* Option markup modified with class added */
output.Write("<option value=\"" + this.GetItemValue(obj) + "\"" + (flag2 ? " selected=\"selected\"" : string.Empty) + " class=\"" + obj[StyleClassField] + "\" >" + itemHeader + "</option>");
}
bool flag3 = !string.IsNullOrEmpty(this.Value) && !flag1;
if (flag3)
{
output.Write("<optgroup label=\"" + Translate.Text("Value not in the selection list.") + "\">");
output.Write("<option value=\"" + this.Value + "\" selected=\"selected\">" + this.Value + "</option>");
output.Write("</optgroup>");
}
output.Write("</select>");
if (!flag3)
return;
output.Write("<div style=\"color:#999999;padding:2px 0px 0px 0px\">{0}</div>", Translate.Text("The field contains a value that is not in the selection list."));
}
}
}
This field adds a custom properties to allow you to specify the linked field to use for the style class. The assumption is that you have another single line text field on the linked item to specify the CSS class.
Usage: Set the source property of the field in the following format:
Datasource={path-or-guid-to-options}&StyleClassField={fieldname}
e.g. Datasource=/sitecore/content/lookup/iconfonts&StyleClassField=IconClassName
To use this new field compile the above code in to project, switch over to the core database and then create a new field type – you can duplicate the existing Droplink field located in /sitecore/system/Field types/Link Types/Droplink. Delete the existing Control field and instead set the ASSEMBLY and CLASS fields to point to your implementation.
You also need to load a custom CSS stylesheet with the style defintions into the Content Editor, which you can achieve that by following this blog post.

KendoUI-Grid, CustomCommand - enable/disable

I wants to enable/disable custom command in kendo-ui grid based on some other column.
How do i achieve that? Below is sample code
#(Html.Kendo().Grid<Model>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(a => a.Name).Width(90);
columns.Bound(a => a.Flag).Width(170);
columns.Command(commands => commands.Custom("ABC").Text("ABC").Click("ABC")).Title ("ABC").Width(130);
...
}
I want to enable/disable ABC command button based on flag value. Please help me.
You cannot do this through the command column.
I would suggest you to create template column which displays button based on your condition. How to execute conditional logic inside a template (or use external function to handle for complex logic) is covered here.
I solved the problem. Below is the sample code.
columns.Bound(a => a.Flag).ClientTemplate(
"# if(Flag == 'Value1') { #" + "<input type='button'
class='info k-button k-button- icontext' onclick='clickhere(#=parameter1#)'
value='ClickHere' />" +
"# } else { #" +
"NormalText" +
"# } #").Width(100).Title("ConditionalButton");
//JavaScript
<script type="text/javascript">
function clickhere(parameter1) {
window.location.href = '#Url.Action("Event", "Home")' +
'?parameter1=' + parameter1;
}
</script>

Customizing Struts Displaytag table properties

I have knowledge on how to customize the display data using Struts2 displaytag:table and decorator.
But I need to customize the table columns (tr style)
public String getWorkFlow() {
WorkOrderDO currentWorkOrder = (WorkOrderDO) getCurrentRowObject();
String output = null;
if (currentWorkOrder.getChildId() == 0) {
if (!currentWorkOrder.isWorkFlowRetrieved()) {
output = "<input type = 'submit' value = 'Work Flow' id=" + currentWorkOrder.getMoveWorkOrderId() + " onclick = 'changeWorkOrder(this);return false;'/>";
} else {
output = "<input type = 'submit' value = 'Work Flow' id=" + currentWorkOrder.getMoveWorkOrderId() + " onclick = 'changeWorkOrder(this);return false;' disabled/>";
}
}
return output;
}
from above method in decorator class, we can customize the data look and feel.
But my question is, if currentWorkOrder.isWorkFlowRetrieved() == true, I want to highlight the entire column (tr) in the table in the display page with style property
Any idea?
you can do this by using style attribute in the display:column tag
for eg
I hope this works for you.