Kendo MVC Grid ClientTemplate will lead to "Field not defined" - asp.net-mvc

I have a kendo MVC Grid which read action can be done successfully
#(Html.Kendo().Grid<MyModel>()
.Name("Name")
.AutoBind(false)
.Columns(columns =>
{
...
columns.Bound(c => c.ItemCode).ClientTemplate("#= ItemCode #").Title("Item").Width(300);
})
.Pageable(page =>
{
page.Enabled(true);
})
.Scrollable(s => s.Height(400))
.Sortable(s => s.Enabled(false))
.Editable(ed => ed.Mode(GridEditMode.PopUp).TemplateName("MaterialFormEditor").Window(w => { w.Title(""); w.Width(700); }).DisplayDeleteConfirmation(false))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Model(model => model.Id(p => p.JobNo))
.Read(read => read.Action(...)
.ServerOperation(true)
)
)
public class MyModel
{
public string ItemCode;
}
(Above code is simplified, so the ClientTemplate content is simply the field value itself, yet the problem still can be reproduced)
Now the problem is, when I click the "Add new record" button, a javascript error comes out and no window is popped up.
The error said: Uncaught ReferenceError: ItemCode is not defined
Yet when I delete the .ClientTemplate(), everything goes right.
What is the cause of the error and how can I solve it?

Old question, I know...
I had a similar issue and had to add backslashes to get it to work:
columns.Bound(c => c.ItemCode).ClientTemplate("\\#= ItemCode \\#").Title("Item").Width(300);

Related

Telerik Kendo Grid Doesn't Display Value Properly

i'm new to kendo UI and currently learning about custom editor.
My Problem is i managed to get my editor template working in edit mode and populate the data just fine, but somehow it won't save the value to the display grid
I Retreive all my data from API.
UPDATE:
i've managed to properly save the value from the custom editor template to the controller and it works just fine, but using clientTemplate won't display the correct value from what i select in the dropdown, and only show a string
DropDown Only Display A String
my setup code is like this
#( Html.Kendo().Grid<SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Product).ClientTemplate("\\#=Product.ProductId\\#").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Batch(true)
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product);
})
.Create(act => act.Action("DetailCell_Create","SalesOrder"))
)
)
DDLProduct.cshtml:
#model AAF.WEB.MVC.ViewModels.ProductVM
#(
Html.Kendo().DropDownListFor(m => m)
.DataValueField("ProductId")
.DataTextField("ProductName")
.OptionLabel("Select Product")
.BindTo((System.Collections.IEnumerable)ViewData["products"])
)
Edit Mode
DisplayMode / Out of Product Edit Mode
Use template method to acheive dropdown with kendo grid.
GridForeignKey.cshtml - it should placed in shared folder or EditorTemplates
#model object
#(
Html.Kendo().DropDownListFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
In your kendo grid please change like below
#( Html.Kendo().Grid<AAF.WEB.MVC.ViewModels.SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Id)
columns.ForeignKey(c => c.ProductId, (System.Collections.IEnumerable)ViewData["Products"], "ProductId", "ProductName").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
)
You can set the products data to view data. using this method you can save the product id.
Thanks
Okay after i frustrated for many hours, finally found the solution
the solution is to add a defaultvalue to the passed model in the grid
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product).DefaultValue(
ViewData["defaultProduct"] as ProductVM
);
})
and pass the data from the controller
// Function that get data from API
ViewData["products"] = products;
ViewData["defaultProduct"] = products.First();

Dropdown list in ASP MVC Kendo grid will not open

I am trying to replicate exactly what is on this Kendo demo page with the Categories column. Simply a drop down list inside the grid. I copied all their source code exactly, but when I click the column with a drop down, the grid simply flashes. I can edit the FullName value fine. I tried to get an animation of the effect with a screen recorder, but for some reason it is not showing everything I see. In this image I am clicking the "Rol" drop down column multiple times.
What the gif does not show is that when I click the column, it briefly changes to a drop down control for a split second. I was able to capture this by adding a "debugger" line to the onDataBound event for the dropdown and taking a screenshot:
What is going on? Why doesn't it just pop open?
Here is some of the relevant code:
The EditorTemplates/RolList.cshtml file. Note that NONE of these events fire except the onDataBound event. That is probably a clue.
#model MyCompany.Web.CaseLink.Mvc.Admin.Models.RolDropDown
#(Html.Kendo().DropDownListFor(m => m)
.BindTo((System.Collections.IEnumerable)ViewData["roles"])
.DataValueField("RolId")
.DataTextField("RolDescription")
.Events(events => events
.Select("onSelect")
.Change("ddlChange")
.Open("onOpen")
.DataBound("onDatabound")
)
)
<script type="text/javascript">
function onSelect(e) {
console.log("ddl select" + e);
}
function ddlChange(e) {
console.log("ddl change" + e);
}
function onOpen(e) {
console.log("ddl open" + e);
}
function onDatabound(e) {
debugger;
console.log("ddl databound" + e);
}
</script>
Here is the partial view containing the MVC Grid itself. Note that the gridChange event was added just for debugging, and it does not fire when clicking in the drop down column.
#(Html.Kendo().Grid<CaseMemberGridRow>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.FullName)
.Title("Name")
;
columns.Bound(p => p.Rol).ClientTemplate("#=Rol.RolDescription#").Width(180);
columns.Bound(c => c.Email)
.Title("Email")
;
columns.Bound(c => c.Telephone)
.Title("Phone")
;
columns.Command(command => command.Destroy()).Width(150);
})
.ToolBar(toolBar =>
{
toolBar.Create();
toolBar.Save();
})
.HtmlAttributes(new { style = "height: 550px;" })
.Scrollable()
.Sortable()
.Editable(editable => editable.Mode(GridEditMode.InCell))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("error_handler").Change("gridChange"))
.Model(m =>
{
m.Field(p => p.FullName).Editable(true);
m.Field(p => p.Rol).Editable(true);
m.Field(p => p.Rol).DefaultValue(
ViewData["defaultRol"] as MyCompany.Web.CaseLink.Mvc.Admin.Models.RolDropDown);
})
.Create(create => create.Action("AddCaseMemberNoCustomerRecord_Create", "AddMember"))
.Update(update => update.Action("AddCaseMemberNoCustomerRecord_Update", "AddMember"))
)
)
Controller is nothing special, as I said, I am doing exactly when Telerik did in their demo. A sample:
var roles = _rolService.GetAllRolesDTO()
.OrderBy(o => o.Description)
.Select(r => new RolDropDown
{
RolDescription = r.Description,
RolId = r.RolId
});
ViewData["roles"] = roles;
ViewData["defaultRol"] = roles.First();
If there is something to look for in the debugger on the "onDataBound" event, let me know. As you can see here, the datasource is definitely populated.
EDIT: I am aware that you can attempt to do the same thing using the ForeignKey type of column. When I try that, I can get a drop down to work once. After selecting a value, the column starts acting like before where you cannot change the value.
columns.ForeignKey(p => p.RolId, (System.Collections.IEnumerable)ViewData["roles"], "RolId", "Description")
.Title("Role")
.Width(150);

KendoUI Edit Issue

Kendo UI edit option showing some unexpected behaviour, as you can see in the image there is a text box below Server column and 2 below ServerIP column all containing the id of server "SQL" i selected. Problem is when ever i want to show Server IP column this behaviour occurs, both server and server IP are from the same table.
#(Html.Kendo().Grid<EnvironmentPOCO>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(d => d.EnvironmentName).Width(200).Title("EnvirontmentName");
columns.ForeignKey(d => d.EnvironmentTypeID, (List<EnvironmentTypePOCO>)ViewData["EnvironmentType"], "EnvironmentTypeID", "EnvironmentTypeCode").Width(150).Title("EnvironmentCode").EditorTemplateName("_EnvironmentCodeDropDown");
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerName").Width(200).Title("Server").EditorTemplateName("_ServerDropDown");
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerIP").Width(200).Title("ServerIP");
columns.ForeignKey(d => d.ProjectID, (List<ProjectPOCO>)ViewData["Projects"], "ProjectID", "ProjectName").Width(200).Title("ProjectName").EditorTemplateName("_ProjectNameDropDown");
// columns.ForeignKey(d => d.ProjectID, (List<ProjectPOCO>)ViewData["Projects"], "ProjectID", "ProjectDescription").Width(200).Title("ProjectDescription")/*.EditorTemplateName("_ProjectDescription")*/;
columns.Command(d =>
{
d.Edit();
d.Destroy();
}).Width(200).Title("Action");
})
.ToolBar(tools => tools.Create())
.Sortable()
.Pageable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(m => m.EnvironmentID);
model.Field(m => m.EnvironmentName);
model.Field(m => m.EnvironmentTypeID);
model.Field(m => m.ProjectID);
model.Field(m => m.ServerID);
})
.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 found a solution to this, actually if you want to show 2 fields of the foriegn key, You can make a property in your class.
public string ServerDetailsProperty
{
get
{
return string.Format(" Name: {0} || IP: {1}", ServerName, ServerIP);
}
}
then call it in your csHTML file like this.
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "**ServerDetailsProperty**").Width(200).Title("ServerIP");
Now if you press Edit you want see the unexpected behiour as in the diagram.
Try Changing the id and name attribute of the Server IP columns as the Grid is not able to differentiate between the Server Column and Server IP column on Edit.
For your reference I have tried below:
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerIP").Width(200).Title("ServerIP").HtmlAttributes(new { #id="ServerIP_#=ServerIP#", #name="ServerIP_#=ServerIP#" })
Let me know if this doesn't solve your issue.
EDIT:
You can add the dropdown in client template as below:
columns.Bound(s => s.ServerID).ClientTemplate((#Html.Kendo().DropDownList()
.BindTo((List<ServerPOCO>)ViewData["ServerDetails"])
.Name("ServerIP#=ServerIP#")
.DataTextField("ServerIP")
.DataValueField("ServerID")
.ToClientTemplate()).ToHtmlString());
On Grid DataBound event set the grid scripts to load with document as below:
function onGridDataBound(e) {
$('#GridName script').appendTo(document.body);
}
Finally set the field to readonly in model meta:
model.Field(s => s.SensorID).Editable(false);
For further information have a look at the explaination: Dropdown in Column Client Template

kendo grid filter does not work with nested property

I've got a grid
#(Html.Kendo()
.Grid<Entity>()
.Columns(column =>
{
column.Bound(i => i.Date);
column.Bound(i => i.User.FirstName);
})
.DataSource(data => data.Ajax()
.ServerOperation(true)
.Read(read => read.Action("index", "app")))
)
but in case filtering by firstname, gets filter property Member = "undefined"
any ideas how to figure it out?

Grid into Grid Popup Editor - Passing ID parameter in sub grid

I have a Grid with Employes. There is a Edit button and the edit mode is set to Popup. In the EditorTemplate of the entity I want to edit, there is another grid that has a history of Salary with a incell or inline edit mode.
Both grids uses Ajax datasources. The problem is with the inner grid binding. The controller action feeding a Json result to the ajax call requires the ID of the employe we are editing to return the appropriate Salary history. However, Kendo UI ASP.NET MVC wrapper will render some sort of template of the editor before knowing which employee we want to edit, then it will edit it when we are requesting the popup.
How can I feed the Employe ID in the Read Ajax call?
Main Grid
#(Html.Kendo().Grid<MyProject.Business.Models.EmployeDTO>().Name("EmployeGrid")
.ToolBar(toolbar => toolbar.Create())
.Columns(cols =>
{
cols.Bound(o => o.someData).Title("Some Data");
cols.Bound(o => o.moreData).Title("More Data");
cols.Command(o =>
{
o.Edit();
o.Destroy();
}).Title(" ");
})
.Editable(editor => editor
.Mode(GridEditMode.PopUp)
.Window(window => window.Draggable().Resizable().HtmlAttributes(new { #style = "width:700px;" })))
.Sortable()
.Filterable()
.Groupable()
.DataSource(datasource => datasource
.Ajax()
.Model(model => model.Id(o => o.id))
.Read(read => read.Action("GetAll", "EmployesAjax"))
.Update(update => update.Action("Update", "EmployesAjax"))
.Create(create => create.Action("Create", "EmployesAjax"))
.Destroy(destroy => destroy.Action("Destroy", "EmployesAjax"))
)
)
Inner Grid (In Views/Shared/EditorTemplates/EmployeDTO.cshtml)
#Html.Kendo().Grid<MyProject.Business.Models.SalairyDTO>().Name("SalaryGrid")
.Columns(cols =>
{
cols.Bound(o => o.someInfo).Title("Some Info");
})
.DataSource(datasource => datasource
.Ajax()
.Model(model =>
{
model.Id(o => o.id);
model.Field(o => o.employe_id).DefaultValue(Model.id);
})
// NEED THE ID HERE
.Read(read => read.Action("GetByEmployeId", "SalairyAjax", new { id = "" }))
.Update(update => update.Action("Update", "SalairyAjax"))
.Create(create => create.Action("Create", "SalairyAjax"))
.Destroy(destroy => destroy.Action("Destroy", "SalairyAjax"))));
Basically I would suggest you to Set the AutoBind option to false of the inner Grid and use the edit event of the outer Grid to perform a read request and pass the value as additional parameter.
Here is an example:
function onEditOfEmployeGrid(e){
$('#SalaryGrid').data().kendoGrid.dataSource.read({id:e.model.EmployeeID})
}
You could simply pass the value from the grid using addtionaldata parameter within the grid. the RouteID on the (left side) can then be referenced within the Grid Popup Editor using ViewData["RouteID"]. I hope that helps
.Editable(editable => editable.Mode(GridEditMode.PopUp)
.TemplateName("busStop")
.DisplayDeleteConfirmation(true)
.Window(window => window.Modal(true).Resizable().Draggable())
.AdditionalViewData(new { RouteID = Model.RouteID }))

Resources