Dynamically add button to Kendo UI Grid MVC - button

i created a simple web app in .net MVC that contains a simple input textbox and a grid (showing some DB data).
#(Html.Kendo().Grid<Z.ViewModels.ZViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Number);
columns.Bound(c => c.AddedDate);
columns.Bound(c => c.ProcessingMessageText);
columns.Bound(c => c.ProcessedDate).
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Read", "Home"))
.PageSize(20)
)
)
Now i need to add another feature to this page ... if there is no value (" ") in ProcessedDate display a Button with som custom functionality (call an action from controller with parameter from Number column), else display the value.
Is this possible ?
I tried something like thisClientTemplate("# if (ProcessingMessageText =='') {# <button>do stuff</button> #} else if (ProcessingMessageText !='') {# ProcessedDate <#}# ");
}).Events(e => e.DataBound("onDataBound")) but it didnt worked.
I have a function to change the rows color ... but i dont know how to access the column values...
function onDataBound(e) {
var grid = this;
var currentRecords = grid.dataSource.view();
for (var i = 0; i < currentRecords.length; i++) {
//currentRecords[i] is the current dataItem
if (currentRecords[i].ProcessingMessageText == "Finished") {
grid.tbody.find("tr[data-uid='" + currentRecords[i].uid + "']").addClass("rowSucess");
}
if (currentRecords[i].ProcessingMessageText == "Sent") {
var row= grid.tbody.find("tr[data-uid='" + currentRecords[i].uid + "']").addClass("rowSent");
}
else if (currentRecords[i].ProcessingMessageText == "Error") {
grid.tbody.find("tr[data-uid='" + currentRecords[i].uid + "']").addClass("rowError");
}
}
}
Thanks for any help

Using a template column that calls your MVC action and passes a parameter(number) is fairly straight forward. This example creates a bootstrap button to call my controller and pass it the parameter named 'number' using kendo hash tag syntax. Carefull with the single vs double quotes.:
columns.Template(t => { }).Title(string.Empty).Width(40)
.ClientTemplate(#"<a href='" + Url.Action("MyAction","MyController") + "?number=#= Number#' class='btn btn-info btn-xs' title='Modify this item'>Edit</a>");
You would need to add your if statement to show the date if the field is not empty, otherwise show the button.

Related

ClientGroupHeaderTemplate in Excel Export (Kendo ASP.NET MVC)

I have a grid that shows a list of financial arrears grouped by the type of debt, known as Cash Type. These Cash Types can be categorised in a number of ways, or not, which is "Normal". When they are categorised I'm adding a lovely badge in the ClientGroupHeaderTemplate so it stands out to the user. All good so far.
#(Html.Kendo().Grid(Model.Arrears)
.Name("arrearsGrid-" + Model.LeaseId.ToString())
.HtmlAttributes(new { #class = "smallergrid" })
.Columns(columns =>
{
columns.Bound(p => p.InvoiceNumber)
.ClientTemplate("<a class=\"text-primary\" href=\"" + Url.Action("Invoice", "Arrear") + $"/#=InvoiceNumber#?buildingid=#=BuildingId#&leaseid={Model.LeaseId}\" target=\"_blank\">#=InvoiceNumber#</a>");
columns.Bound(p => p.InvoiceDescription);
columns.Bound(p => p.CashType)
.ClientGroupHeaderTemplate("Cash Type: #= getCashTypeName(data.value) # (#= getDebtCategoryName(data.items[0].DebtCategory) #)");
columns.Bound(p => p.InvoiceDate);
columns.Bound(p => p.TransactionDate);
columns.Bound(p => p.DaysOverdue);
columns.Bound(p => p.InvoiceGross)
.HtmlAttributes(new { #class = "text-right" });
columns.Bound(p => p.OutstandingGross)
.HtmlAttributes(new { #class = "text-right" });
})
.Sortable()
.Excel(excel => excel
.FileName("Kendo UI Grid Export.xlsx")
.Filterable(true)
.AllPages(true)
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Group(g => g.Add(p => p.CashType))
)
.NoRecords(x => x.Template("<div class='empty-grid'></div>"))
)
The problem is the Export to Excel function does no processing on the ClientGroupHeaderTemplate, and shows<span>Cash Type: Rent <span class="d-print-none badge debt-category-1 ml-2">In Query</span></span> in the spreadsheet.
Here's the options I see are available, and some I've discounted. Are these really the best options I have?
CSS (rejected)
As you can see, using the Bootstrap d-print-none does nothing. From all the posts on Export and hidding columns, it seems that Kendo is in no way using a print view of the page, so #media options aren't going to help.
excelExport event
Use the Kendo excelExport event to customise the generated Excel workbook, however, this example is document creation. If I'm going this route I suspect it might be easier to write one from scratch, rather than workaround Kendo limitations. Either way it's a lot of work to remove 1 line of HTML markup.
Use the ProxyURL
Under a Grids Excel object, you can set an endpoint to call when the Excel spreadsheet is created. This might give the chance to tweak a ready-to-save spreadsheet before it is saved. There's a demo of it here. The demo is wrong (the Controller name is not Grid, it's Excel_Export) and it doesn't work for me even when corrected and the standard .ToolBar(tools => tools.Excel()) back in. Maybe it's because I'm not AJAXing my data in, or maybe it's just as broken as the demo. Changing my grid to AJAX will is not beyond the realms of possibility, but it's not a small job either.
Edit: I got this to hit the event by also adding .ForceProxy(true) to the Excel definition. This isn't mentioned in the demo, and the statement that you need to add .ToolBar(tools => tools.Excel()) is also incorrect; you can fire the event from your own buttons that trigger the Excel export.
Give up and go simple
The last option I have is to give up on the badges and just have text. It's the quickest and surest option, but it's solving the problem by ignoring the problem.
So I managed this in yet another way. I'm sure there must be an MVC answer to this problem though.
I added an event to my Grid
#(Html.Kendo().Grid(Model)
...
.Events(e =>
{
e.ExcelExport("exportExcel");
}
...
)
and created a JavaScript middleware function to alter the Excel file before it is saved. Of course you can then do whatever JS allows you to do at this point.
In the code below are examples of setting a column width (4), removing HTML span markup, and converting a string to a number and adding a currency format to that number (7). The method of obtaining the currency symbol is not pretty, but it's a string inside some HTML markup, I don't think it can be pretty.
function exportExcel(e) {
var sheet = e.workbook.sheets[0];
var lastRow = sheet.rows[sheet.rows.length - 1];
var lastCell = lastRow.cells[lastRow.cells.length - 1];
var lastCellValue = lastCell.value.toString().replace(/<[^>]*>/, "").replace("</span>", "");
var currency = lastCellValue.substring(0, 1);
currency += "#,###,##0.00";
sheet.columns[4].autoWidth = false;
sheet.columns[4].width = 125;
$.each(sheet.rows, function (index, row) {
if (index > 0) {
if (row.cells[0] != undefined) {
if (row.cells[0].value != undefined) {
row.cells[0].value = row.cells[0].value.replace(/<[^>]*>/, "(").replace("</span>", ")");
}
}
if (row.cells[7] != undefined) {
if (row.cells[7].value != undefined) {
row.cells[7].value = row.cells[7].value.toString().replace(/<[^>]*>/, "").replace("</span>", "");
row.cells[7].value = Number(row.cells[7].value.toString().replace(/[^0-9\.-]+/g, ""));
row.cells[7].format = currency; // Why this prepends a backslash to the format I do not know
}
}
}
});
};

KendoUI grid checkbox column

Currently I am having this code for displaying a KendoUI grid:
#(Html.Kendo().Grid<CleverFit.Models.MyHistorie>()
.Name("grid")
.DataSource(dataSource => dataSource // Configure the grid data source
.Ajax() // Specify that ajax binding is used
.Read(read => read.Action("Products_Read", "Action")) // Set the action method which will return the data in JSON format
)
.Columns(columns =>
{
columns.Bound(product => product.Datum).Format("{0:dd.MM.yyyy}");
columns.Bound(product => product.Aktion);
columns.Bound(product => product.Ergebnis);
columns.Bound(product => product.Wiedervorlage).Format("{0:dd.MM.yyyy H:mm}");
columns.Bound(product => product.Bemerkung);
columns.Bound(product => product.Erledigt);
})
.Pageable() // Enable paging
.Sortable() // Enable sorting
)
I tried already this:
columns.Bound(product => product.Erledigt).ClientTemplate(
"<input type='checkbox' value='#= ProductID #' " +
"# if (Enabled) { #" +
"checked='checked'" +
"# } #" +
"/>"
);
But if I add this, there is no data displayed in the grid...
The values of the last column which is product.Erledigt are displayed as true or false. Is it possible to display them as checkboxes?
I am using Telerik KendoUI and loading the content of the template via AJAX.
You can check the following FAQ page:
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/faq#how-to-display-checkboxes-in-ajax-bound-grids
In addition, you can make the checkbox readonly or disabled to prevent the user from editing it and expect the changes to be persisted.
Update
The code that you have tried contains two data field values, which obviously do not exist in your Grid: ProductID and Enabled. Most probably you are getting a JavaScript error in the browser console. Replace Enabled with Erledigt and remove value='#= ProductID #' if you don't need such a thing.

Kendo Grid Client Detail Template Local Data Binding

I have a Kendo Grid with a Kendo ListView for its client detail template.
Here is the grid :
#(Html.Kendo().Grid<ITS.BusinessModel.TaskManager.TaskItem>()
.Name("grdPackage" + Model + "sTasks")
.Columns(columns =>
{
columns.Bound(taskModel => taskModel.WorkflowInstanceId);
columns.Bound(taskModel => taskModel.WorkflowInstanceName);
columns.Bound(taskModel => taskModel.Name).ClientTemplate("<a onclick='openTasksForm(#= ID#)' > #= Name # </a>");
}
.ClientDetailTemplateId("TaskSumeriesListViewTemplate")
.AutoBind(false)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(true)
.Model(model => model.Id(Task => Task.ID))
.Read(read => read.Action("TaskItemsList_Read", "Task", new { packageGroupID = Model, packageType = (Model == -2) ? 0 : (Model == -1) ? 1 : 2 }))
)
)
Here is the client template:
<script type="text/x-kendo-tmpl" id="TaskSumeriesListViewTemplate">
#(Html.Kendo().ListView<ITS.BusinessModel.TaskManager.WorkflowInstanceSummaryItem>("#=TaskSumaries#")
.Name("listViewPackage")
.TagName("div")
.ClientTemplateId("SummeriesTemplate")
.ToClientTemplate()
)
</script>
And here is the template for ListView :
<script type="text/x-kendo-tmpl" id="SummeriesTemplate">
<div>
#=ColumnName# : #=ColumnValue#
</div>
</script>
Each TaskItem that Grid reads has a TaskSumariesList which is a List.
I want to use this list in Grid Client Detail for ListView.
How can I do this?
In your Events call for your grid, use something like this:
.Events(e => e.DetailInit("detailInit")
Then, you can do something like this:
function detailInit(e) {
var list= $("#listViewPackage").data("kendoGrid");
list.dataSource.data(e.data.TaskSumariesList)
}
What will happen is that the list will get populated with the appropriate data when it expands.
You may need to do something like this for your List name:
.Name("listViewPackage#=WorkflowInstanceId#")
This way, you can make sure you have the right data for the right list:
function detailInit(e) {
var list= $("#listViewPackage" + e.data.WorkflowInstanceId).data("kendoGrid");
list.dataSource.data(e.data.TaskSumariesList)
}
Actually Sean is right. For more information please refer:
Kendo UI Grid: Detail Template Binding
You can also add DataSource(ds => ds.Ajax()) to your seccond grid.
#(Html.Kendo().ListView<ITS.BusinessModel.TaskManager.WorkflowInstanceSummaryItem>("#=TaskSumaries#")
.Name("listViewPackage")
.TagName("div")
.ClientTemplateId("SummeriesTemplate")
.DataSource(ds => ds.Ajax())
.ToClientTemplate()
)
It seems like Client template is not available for local bound grids.

Is it possible to hide/show Kendo grid column based on user role?

I am using Kendo ui grid in asp.net MVC. Is it possible to hide/show grid column based on user role? Thanks
The simplest way is:
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Id);
columns.Bound(p => p.Name);
if(User.IsInRole("Admin")) {
columns.Bound(p => p.AdminOnlyInfo);
}
})
...
)
You can specify if a column is visible using hidden, so one option may be to set a variable based on the users role. For example, in the controller
ViewBag.CanDisplay = true; // or omit if the user does not have permission
and in the view
var canDisplay = '#ViewBag.CanDisplay' | false;
$("#grid").kendoGrid({
columns: [
{ field: "firstProperty" },
{ field: "anotherProperty", hidden: !canDisplay }
],

How to access KendoUI Grid selected row Hash Template(KendoUI) value in KendoUI Tabstrip

I am using kendoUI Detail view template, as shown in the image
When i click on on each row it opens a tabstrip and displays all the data stored in the ViewData for e.g
The main grid Code is shown Below,
#(Html.Kendo().Grid<EnvironmentPOCO>()
.Name("Grid")
.Columns(columns =>
{
//columns.Bound(d => d.EnvironmentID).Visible(false);
columns.Bound(d => d.EnvironmentName).Width(200).Title("Environment Name");
columns.ForeignKey(d => d.EnvironmentTypeID, (List<EnvironmentTypePOCO>)ViewData["EnvironmentType"], "EnvironmentTypeID", "EnvironmentTypeCode").Width(150).Title("Environment Code").EditorTemplateName("_EnvironmentCodeDropDown");
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["MyServers"], "ServerID", "ServerDetailsProperty").Width(300).Title("Server Details").EditorTemplateName("_ServerDropDown");
columns.ForeignKey(d => d.ProjectID, (List<SynergyProjectPOCO>)ViewData["MySynergyProjects"], "ProjectID", "ProjectDetailsProperty").Width(400).Title("Project Details").EditorTemplateName("_ProjectNameDropDown");
columns.Command(d =>
{
d.Edit();
d.Destroy();
}).Width(200).Title("Action");
}
)
.ToolBar(tools => tools.Create())
.Sortable()
.Pageable()
.Filterable()
.Navigatable()
.Sortable(sortable => sortable.AllowUnsort(false))
.ClientDetailTemplateId("template")
.HtmlAttributes(new { style = "height:430px;" })
.Events(events => events.DataBound("dataBound"))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(m => m.EnvironmentID);
})
.Read(read => read.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Get))
.Create(create => create.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Post))
.Update(update => update.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Put))
.Destroy(destroy => destroy.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Delete))
)
)
I have a viewdata which have all the details i want to show in the tabstrip, but what i want is it should only display the data only related to the rows selected ServerID....there should be a if check in for loop for e.g if(//above grid ServerID==viewdata ServerID display that row of view data).But i dont know how to access the above grid value in the tabstrip and how to use if in cshtml razor engine. See the if check which is not working in Tabstrip code is shown below
<script id="template" type="text/kendo-tmpl">
#(Html.Kendo().TabStrip()
.Name("Logins")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().Text("Contact Information").Content(#<div>
<ul>
#for (var i = 0; i < viewDataServer.Count; i++)
{ //How to get the Top Grid ServerID value here in **if**
#if("#=ServerID"==viewDataServer[i].ServerID.ToString())//#=ServerID should be the selected main grid serveridvalue
{
<li><label>LoginID:</label>#viewDataServer[i].LoginID.ToString()</li>
<li><label>ServerID:</label>#viewDataServer[i].ServerID.ToString()</li>
<li><label>UserID:</label>#viewDataServer[i].UserID.ToString()</li>
<li><label>Password:</label>#viewDataServer[i].passwd.ToString()</li>
}
}
</ul>
</div>);
})
.ToClientTemplate())
</script>
In case any one else have this issue, here is the solution.
The detail template of the Grid is a client template, which means that all content customizations depending on the master row must be managed from the client. Currently the TabStrip uses server-side logic that relies on a parameter (ServerID), which is available only on the client, that's why the server logic does not work as expected.
You need to populate the TabStrip via an Ajax request, which will pass the ServerID
items.Add().Text("Contact Information")
.LoadContentFrom(Url.Content("~/controller/action/?ServerID=#=ServerID#"));
http://demos.telerik.com/aspnet-mvc/tabstrip/ajax
For more advanced customization that require manual coding, you can use the Grid's detailInit event, as shown here:
http://demos.telerik.com/kendo-ui/grid/detailtemplate

Resources