I have worked for days now trying to figure out how to add a mutliselect control to a kendo UI grid column. I have the following structures:
public class CampaignOrgModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CampaignViewModel
{
public int CampaignID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<CampaignOrgModel> CampaignOrgList { get; set; }
}
and my UI is:
var dataSource = new kendo.data.DataSource({
...
schema:
{
model:
{
id: "CampaignID",
fields:
{
id: { type: "number", editable: false },
Name: { type: "string" },
Descirption: { type: "string" },
CampaignOrgList: { }
}
}
}
});
$("#campaignGrid").kendoGrid({
dataSource: dataSource,
...
columns:
[
{ field: "Name", title: "Name" },
{ field: "Description", title: "Description" },
{
field: "CampaignOrgList",
title: "Organizations"
}
]
});
I have 2 issues:
Currently, the "Organizations" column only shows [object object] for each row. I know I have to use a column template to show the Organization names but I don't know how to do that. I have looked at examples and can't figure out how to make it work for my scenario.
I need the multi-select to allow the user to select from the entire list of organizations available. Not just the ones that are assigned to the selected row. for example: there may be ["Org 1", "Org 2", "Org 3"] available but the row i'm editing may only be assigned to "Org1". in this example, "Org 1" should show in the grid but all 3 need to show in the multi-select editor to allow the user to add additional organizations to the campaign.
Link http://dojo.telerik.com/#harsh/Uceba
//organizations array datasource for multiselect
var organizations_arr = ['org1', 'org2', 'org3', 'org4'];
//grid data
var data = [{
Name: 'abc',
Organizations: ['org1', 'org4']
}, {
Name: 'def',
Organizations: ['org3']
}];
//multiselect editor for Organization field
function orgEditor(container, options) {
$("<select multiple='multiple' data-bind='value :Organizations'/>")
.appendTo(container)
.kendoMultiSelect({
dataSource: organizations_arr
});
}
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
data: data
},
height: 150,
sortable: true,
editable: true,
columns: [{
field: "Name",
width: 200
}, {
field: "Organizations",
width: 150,
template: "#= Organizations.join(', ') #",
editor: orgEditor
}]
});
});
Related
Using kendo grid edit event I want to disable field name and id during Edit mode. I manage to disable id by following this example here. But went I try to disable name seem it not working, any thought how to do this?
WORKING DEMO IN DOJO
$("#grid").kendoGrid({
columns: [
{ field: "id" },
{ field: "name" },
{ field: "age" },
{ command: "edit" }
],
dataSource: {
data: [
{ id: 1, name: "Jane Doe", age: 30 },
{ id: 2, name: "John Doe", age: 33 }
],
schema: {
model: {
id: "id",
fields: {
"id": { type: "number" },
"name": { type: "string" }
}
}
}
},
editable: "inline",
toolbar:["create"],
edit: function(e) {
if (!e.model.isNew()) {
var numeric = e.container.find("input[name=id]").data("kendoNumericTextBox");
numeric.enable(false);
//var x = e.container.find("input[name=name]").data("kendoTextBox");
//x.enable(false);
//$("input[name=name]").prop("disabled", true).addClass("k-state-disabled");
//$("input[name=name]").editable = false;
}
}
});
by using editable function i created this
function isEditable(e){
var dataSource = $("#grid").data("kendoGrid").dataSource;
return (e.id == null || e.id == '');
}
and add this into the grid > column
columns: [
{ field: "id", editable: isEditable },
{ field: "name", editable: isEditable },
{ field: "age" },
{ command: "edit" }
],
Full working demo is here
I have three dropdowns (Category, Language, Product). Product can be choosen after Category and Language is selected. Then I need to load data for Product dropdown from server:
All dropdowns load data from server as JSON
Data for Product dropdown is selected by CategoryId (int) + Language (string)
Solving this issue requires:
MVC view with input fields (Kendo generates drop downs using the javascript)
JavaScript for KendoUI dropdown logic and data binding
Controllers with actions providing JSON data for dropdown menus
Special classes for filtering data (filter is needed on Product dropdown data bind)
Step by step:
1. MVC View
<input id="Category" required="required" name="Category" />
<input id="Language" required="required" name="Language" />
<input id="ProductId" required="required" name="ProductId" />
2. Script for MVC View
<script>
$(document)
.ready(function () {
var categories = $("#Category")
.kendoDropDownList({
autoBind: false,
optionLabel: "Select category...",
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
type: "json",
serverFiltering: true,
transport: {
read: "#Html.Raw(Url.Action("GetProductCategories", "OfflineLicenses"))"
}
}
}).data("kendoDropDownList");
var languages = $("#Language")
.kendoDropDownList({
autoBind:false,
optionLabel: "Select language...",
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
type: "json",
serverFiltering: true,
transport: {
read: "#Html.Raw(Url.Action("GetProductLanguages", "OfflineLicenses"))"
}
}
})
.data("kendoDropDownList");
var products = $("#ProductId")
.kendoDropDownList({
autoBind: false,
enable: false,
optionLabel: "Select product...",
dataTextField: "Name",
dataValueField: "Sku",
dataSource: {
type: "json",
serverFiltering: true,
transport: {
read: {
url: "#Url.Action("GetProducts", "OfflineLicenses")",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8"
},
parameterMap: function (options) {
return JSON.stringify(options);
}
}
}
}).data("kendoDropDownList");
languages.bind("cascade", cascade);
categories.bind("cascade", cascade);
function cascade() {
if(languages.value() && categories.value()) {
products.enable(true);
products.dataSource.filter([
{ field: "Language", operator: "eq", value: languages.value() },
{ field: "CategoryId", operator: "eq", value: parseInt(categories.value()) },
]);
} else {
products.value("");
products.enable(false);
}
}
});
</script>
3. Controller methods
public ActionResult GetProductLanguages()
{
return Json(Languages.Select(x => new { Id = x.Name, x.Name }).ToList(), JsonRequestBehavior.AllowGet);
}
public ActionResult GetProductCategories()
{
return Json(Categories.Select(x => new { x.Id, x.Name }).ToList(), JsonRequestBehavior.AllowGet);
}
public ActionResult GetProducts([FromUri]FilterContainer filter = null)
{
// use filter by your own
return Json(Products.OrderBy(x => x.Name)
.Select(x => new { Sku = x.Sku, x.Name }).ToList(), JsonRequestBehavior.AllowGet);
}
4. Kendo filter classes
public class SortDescription
{
public string field { get; set; }
public string dir { get; set; }
}
public class FilterContainer
{
public FilterDescription[] filters { get; set; }
public string logic { get; set; }
}
public class FilterDescription
{
public string #operator { get; set; }
public string field { get; set; }
public string value { get; set; }
}
Do not forget to check your property names (I am using some special property names in this example).
I have a Kendo UI grid which is set to use inline editing. One column in the grid uses a template and an editor. When I make changes to this column and I click Update for the row, the update in the datasource does not get called.
The column displays a comma-separated list of text in display mode and a multi-select box in edit mode.
Here is my datasource:
var userDataSource = new kendo.data.DataSource({
autoSync: true,
transport: {
read: {
url: "#Url.Action("ManagedUsers", "Manage")" + $("#suppliers").val(),
dataType: "json"
},
update: {
url: "#Url.Action("UpdateUser", "Manage")",
type: "POST"
},
destroy: {
url: "#Url.Action("DestroyUser", "Manage")",
type: "POST"
}
},
schema: {
model: { id: "Id" },
fields: {
Id: { editable: false, nullable: true },
Email: { validation: { required: true } },
IsAdmin: { type: "boolean" },
IsManager: { type: "boolean" },
SupplierRoles: { type: "object" }
}
}
});
And my grid:
var userGrid = $("#userGrid").kendoGrid({
columns: [{
field: "Email",
width: "35%"
},
{
field: "SupplierRoles",
title: "Roles",
template: "#= displayUserSupplierRoles(data.SupplierRoles) #",
editor: userSupplierRoleMultiSelectEditor,
filterable: false,
sortable: false
},
{
field: "IsAdmin",
title: "Admin",
hidden: "#{(!Model.User.IsAdmin).ToString().ToLower();}",
template: "#=IsAdmin ? 'Yes' : 'No' #",
width: "10%"
},
{
field: "IsManager",
title: "Manager",
hidden: "#{(!Model.User.IsManagerForCurrentSupplier).ToString().ToLower();}",
template: "#=IsManager ? 'Yes' : 'No' #",
width: "12%"
},
{ command: ["edit", "destroy"], width: "20%" }],
dataSource: userDataSource,
noRecords: true,
messages: {
noRecords: "There are no users to manage"
},
editable: "inline",
pageable: {
pageSize: 10
},
sortable: true,
filterable: true,
scrollable: true,
resizable: true
});
The editor function for the multi-select column is defined as:
function userSupplierRoleMultiSelectEditor(container, options) {
var selectedRoles = [];
for (var key in options.model.SupplierRoles) {
if (options.model.SupplierRoles[key].HasRole) {
selectedRoles.push(options.model.SupplierRoles[key].Id);
}
}
$("<select data-placeholder='Select roles...'></select>")
.appendTo(container)
.kendoMultiSelect({
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
data: options.model.SupplierRoles,
schema: {
model: { id: "Id" }
}
}
}).data("kendoMultiSelect")
.value(selectedRoles);
}
The grid is populated based upon a user action and done so within this function:
function listUserManagedUsers() {
$.ajax({
url: "#Url.Action("ManagedUsers", "Manage")" + "?supplierName=" + $("#suppliers").val(),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$("#userGrid").data("kendoGrid").dataSource.data(data);
}
});
}
For completeness, I'll include the view model for the grid:
public class ManagedUserViewModel
{
public string Id { get; set; }
public string Email { get; set; }
public bool IsAdmin { get; set; }
public bool IsManager { get; set; }
public List<UserSupplierRole> SupplierRoles { get; set; }
}
public class UserSupplierRole
{
public int Id { get; set; }
public string Name { get; set; }
public bool HasRole { get; set; }
}
When in edit mode, changing the email and clicking on Update calls Update on the datasource. After altering the multiselect and pressing update does not trigger the update call on the datasource.
Can anyone help me with what am I doing wrong?
Thanks!
OK. So I figured out what was going wrong.
Essentially, it was when I bound to the multiselect widget.
Here is the new code:
function userSupplierRoleMultiSelectEditor(container, options) {
$("<select data-placeholder='Select roles...' multiple='multiple' data-bind='value:SupplierRoles'></select>")
.appendTo(container)
.kendoMultiSelect({
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
transport: {
read: function(op) {
var roleCache = localStorage.getItem("roles");
if (roleCache != null || roleCache != undefined) {
op.success(JSON.parse(roleCache));
} else {
$.ajax({
url: "#Url.Action("Roles", "Manage")",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
localStorage.setItem("roles", JSON.stringify(data));
op.success(data);
}
});
}
}
}
}
});
}
I added the data-bind attribute to the select tag and I set it to the roles that the user has. I then set the read in the datasource to get all of the roles.
Once these two pieces were hooked up (with a slight change of the view model), the grid would stay synchronized with its state).
I'm trying to modify this example to invoke a webmethod with the url attribute.
How can I get the constructor to invoke the WebMethod "Test2"?
<script type="text/javascript">
//<![CDATA[
$(function () {
"use strict";
var myFloatTemplate = { width: 80, align: "right", sorttype: "float" };
$("#CompTable").jqGrid({
url: "<%= AdminPath %>WebMethods/WebService1.asmx/Test2",
datatype: "json",
height: "auto",
colNames: ["Part", "Description", "Src", "Std Usage", "Usage Inc Scrap", "Rate Scrap", "UOM", "Item", "Unit Cost", "Stock"],
colModel: [
{ name: "COMP1_PART", width: 120 },
{ name: "WSCOMPDESC", width: 300 },
{ name: "WSCOMPSRC", width: 40 },
{ name: "COMPUSAGE", template: myFloatTemplate },
{ name: "WSGROSSQTY", width: 120, template: myFloatTemplate },
{ name: "COMPRATE_SCRAP", width: 90, template: myFloatTemplate },
{ name: "COMPBASIC_UNIT", width: 60 },
{ name: "COMP1_ITEM", width: 60 },
{ name: "WSCOMPUNITCOST", template: myFloatTemplate },
{ name: "WSCOMPQTYSTOCK", template: myFloatTemplate }
],
jsonReader: {
repeatitems: false,
id: "ID"
},
caption: "Bom Detail",
rowNum: 10000,
autoencode: true,
loadonce: true,
sortable: true,
loadComplete: function () {
var $self = $(this);
if ($self.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$(this).trigger("reloadGrid"); // Call to fix client-side sorting
}, 50);
}
}
});
});
//]]>
</script>
and
[DataContract]
public class JJ
{
[DataMember]
public int ID;
[DataMember]
public string WSCOMPDESC;
[DataMember]
public string WSCOMPUNITCOST;
[DataMember]
public string WSCOMPSRC;
[DataMember]
public int WSCOMPQTYSTOCK;
[DataMember]
public string COMPBASIC_UNIT;
[DataMember]
public float COMPUSAGE;
[DataMember]
public int COMPRATE_SCRAP;
[DataMember]
public float WSGROSSQTY;
[DataMember]
public string COMP1_PART;
[DataMember]
public string COMP1_ITEM;
}
[DataContract]
public class MM
{
[DataMember]
public int total;
[DataMember]
public int page;
[DataMember]
public int records;
[DataMember]
public List<JJ> rows;
}
[WebMethod]
public MM Test2()
{
MM m = new MM();
m.records = 2;
m.page = 1;
m.total = 1;
m.rows = new List<JJ>();
m.rows.Add(new JJ() { COMP1_ITEM = "1", WSCOMPDESC = "A"});
m.rows.Add(new JJ() { COMP1_ITEM = "2", WSCOMPDESC = "B"});
return m;
}
If you don't implemented server side paging of data you should return all data. the simplest format will be array of items. So you can modify the code of the WebMethod Test2 to the following:
[WebMethod]
public object Test2 () {
return new[] {
new { COMP1_ITEM = "1", WSCOMPDESC = "A"},
new { COMP1_ITEM = "2", WSCOMPDESC = "B"}
};
}
Then you should use ajaxGridOptions option of jqGrid to set contentType to "application/json;" or "application/json; charset=utf-8" and use mtype: "POST" if you don't use any other attributes of the WebMethod.
The last important thing is the following: ASMX wraps the returned results to d property. So the returned data looks like
{"d":[{"COMP1_ITEM":"1","WSCOMPDESC":"A"},{"COMP1_ITEM":"2","WSCOMPDESC":"B"}]}
instead of
[{"COMP1_ITEM":"1","WSCOMPDESC":"A"},{"COMP1_ITEM":"2","WSCOMPDESC":"B"}]
So one should use jsonReader: { repeatitems: false, root: "d" } to read the data. The final remark: you can use postData: "" to remove sending of all unneeded parameters by jqGrid.
See here the demo project.
I have the codes below:
public class AlphaNumericReportTesting
{
public string Name { get; set; }
public char Sex { get; set; }
public double Ca { get; set; }
}
The partial view, sampleView.cshtml
#model OnlineReporting.Models.AlphaNumericReportTesting;
<div id="grid"> </div>
<script>
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
data: #Html.Raw(Json.Encode(Model)),
schema: {
model: {
fields: {
Name: { type: "string" },
Sex: { type: "char" },
Ca: { type: "double" }
}
}
},
pageSize: 20
},
height: 550,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
"Name",
{ field: "Sex", title: "Sex", width: "130px" },
{ field: "Ca", title: " Ca", width: "130px" }
]
});
});
but when I run the code, I got an error: "Error to retrieve selected report."
How to show my data by having the set up above?
Please help.
Thanks
In Kendo There is no Char , double Types make them all string , kendo has type "string, boolean, number"
#model OnlineReporting.Models.AlphaNumericReportTesting;
<div id="grid"> </div>
<script>
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
data: #Html.Raw(Json.Encode(Model)),
schema: {
model: {
fields: {
Name: { type: "string" },
Sex: { type: "string" },
Ca: { type: "string" }
}
}
},
pageSize: 20
},
height: 550,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
{ field: "Sex", title: "Sex", width: "130px" },
{ field: "Ca", title: " Ca", width: "130px" }
]
});
});
Also "Error to retrieve selected report" is not relevant to Kendo , check your MVC Action for any server Error
This "Error to retrieve selected report" doesn't come from Kendo UI. I suspect there is another problem with your page. Probably a server-side exception.