I'm having a problem finding a solution related to the Kendo Grid.
I am rendering a kendo dropdown list within a cell of a Kendo Grid. It appears to look fine and all, until the user focuses off or tabs off of the dropdown within the cell. The red hash shows that a change was made, but it's showing the data-value-field of the kendo DDL and not the text. Ok, I realize I can just use the same field from the DS in the dataTextField as I'm using in the dataValueField, but that won't work for me...because when I'm calling create or update, I need to be able to pass the primary key or ID of that selected item back into my web api controller.
Here is the grids DS
function loadContactGrid(vendorID) {
var contactsReadURL = null;
contactsReadURL = "/contacts/getcontacts/" + parseInt(vendorID);
contactGridDS = new kendo.data.DataSource({
transport: {
read: {
url: contactsReadURL,
type: 'GET',
contentType: "application/json; charset=utf-8",
},
update: {
url: "/contacts/UpdateContacts/",
type: 'PUT',
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function(xhRequest, ErrorText, thrownError) {
alert('ERROR!!!\n' + ' xhRequest: ' + xhRequest + '\n' + ' ErrorText: ' + ErrorText + '\n' + ' thrownError: ' + thrownError + '\n');
},
complete: function(e) {
$("#contactGrid").data("kendoGrid").dataSource.read();
}
},
destroy: {
url: "/contacts/DeleteContact/",
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "DELETE"
},
create: {
url: "/contacts/InsertContact/",
contentType: "application/json; charset=utf-8",
type: 'POST',
dataType: "json",
success: function(results) {
alert('Contacts successfully saved!');
},
error: function(xhRequest, ErrorText, thrownError) {
alert('ERROR!!!\n' + ' xhRequest: ' + xhRequest + '\n' + ' ErrorText: ' + ErrorText + '\n' + ' thrownError: ' + thrownError + '\n');
},
complete: function(e) {
$("#contactGrid").data("kendoGrid").dataSource.read();
}
},
parameterMap: function(options, operation) {
if (operation !== "read" && options) {
return JSON.stringify(options.models);
}
if (operation == "create") {
// send the created data items as the "models" service parameter encoded in JSON
return { models: kendo.stringify(data.models) };
}
}
},
batch: true,
scrollable: false,
pageSize: 8,
change: function(e) {
if (e.action == "itemchange" && e.field == "email") {
var model = e.items[0];
if (isEmailValid($('input[name=email]').val()) == false) {
e.items[0].receivereport = false;
}
}
if (e.action == "itemchange" && e.field == "contacttype") {
var model = e.items[0];
//setTimeout(function () {
//$('.k-dirty-cell').focusout(function() {
//alert($(this).text(textOverrideContactType(e.items[0].contacttype)));
//});
//textOverrideContactType(e.items[0].contacttype);
//}, 1000); attempting to change text in cell here failed
}
if (e.action === "remove") {
this.sync();
}
},
schema: {
model: {
id: 'contactid',
fields: {
roletyp_seq: { editable: false, nullable: false, required: true, type: 'string' },
contacttype: { editable: true, nullable: false, required: true, type: 'number' },
roletyp_pk: { editable: false, nullable: false, required: true, type: 'number' },
contactid: { editable: false, nullable: false, required: true, type: 'number' },
vendorid: { editable: false, nullable: false, required: true, type: 'number' },
prevrole_pk: {
editable: false,
nullable: true,
required: true,
type: "number",
}
}
}
},
});
And my grid
$("#contactGrid").kendoGrid({
dataSource: contactGridDS,
navigatable: true,
dataBound: mapContactTypes,
editable: true,
//editable: "inline",
//editable: "popup",
edit: function (input) {
if ($('input[name=receivereport]').is(':focus')) {
//detect if email is valid
//get input immediately before this one
if (isEmailValid($('input[name=receivereport]').parent().prev().text()) == false) {
// disable check box
// alert("invalid");
$('input[name=receivereport]').attr('disabled', 'true');
$('input[name=receivereport]').prop('checked', false);
} else {
// enable check box
// alert("valid");
$('input[name=receivereport]').removeAttr('disabled');
$('input[name=receivereport]').prop('checked', false);
}
}
//when user clicks into or out of a field, if the name in the respective row name is blank, alert the user
var grid = this;
var fieldName = grid.columns[input.container.index()].field;
if (isNameInContactGridPopulated(fieldName) == false) {
alert("You can't leave out a contact name in the row you are editing.");
//disable save button
$('.k-grid-save-changes').addClass('k-state-disabled');
$('.k-grid-save-changes').hide();
} else {
//do nothing
$('.k-grid-save-changes').removeClass('k-state-disabled');
$('.k-grid-save-changes').show();
}
if ($('input[name=contactname]').is(":focus") == true) {
//disable save button
if ($('input[name=contactname]').val() == '') {
$('.k-grid-save-changes').addClass('k-state-disabled');
$('.k-grid-save-changes').hide();
}
}
$('input[name=contactname]').keyup(function() {
if ($(this).val() == '') {
$('.k-grid-save-changes').addClass('k-state-disabled');
$('.k-grid-save-changes').hide();
}
});
$('input[name=contactname]').focusout(function () {
if ($(this).val() != '') {
$('.k-grid-save-changes').removeClass('k-state-disabled');
$('.k-grid-save-changes').show();
}
});
},
toolbar: ["save", "cancel"],
pageable: true,
columns: [
{ field: 'roletyp_seq', title: 'RT Seq.', hidden: true, attributes: { 'class': 'contactCell_roletyp_seq' } },
{ field: 'contacttype', title: 'Contact Type', hidden: false, attributes: { 'class': 'contactCell_contacttype' }, editor: loadContactTypeEditor, width: "200px", template: "#=textOverrideContactType(1)#" },
//{ field: 'contacttype', title: 'Contact Type', hidden: false, attributes: { 'class': 'contactCell_contacttype' }, editor: loadContactTypeEditor, width: "200px", template: "#=textOverrideContactType(contacttype)#" },
//{ field: 'contacttype', title: 'Contact Type', hidden: false, attributes: { 'class': 'contactCell_contacttype' }, editor: loadContactTypeEditor, width: "200px" },
{ field: 'prevrole_pk', title: 'prev role ID', hidden: true, attributes: { 'class': 'contactCell_prevrole_pk' } },
{ field: 'roletyp_pk', title: 'Role Type ID', hidden: true, attributes: { 'class': 'contactCell_roletyp_pk' } },
{ field: 'contactid', title: 'Contact ID', hidden: true, attributes: { 'class': 'contactCell_contactid' } },
{ field: 'vendorid', title: 'Vendor ID', hidden: true, attributes: { "class": 'contactCell_vendorid' } },
{ field: 'contactname', title: 'Name', hidden: false, attributes: { "class": 'contactCell_contactname' } },
{ field: 'workphone', title: 'Phone', hidden: false, attributes: { "class": 'contactCell_phone' } },
{ field: 'mobilephone', title: 'Cell', hidden: false, attributes: { "class": 'contactCell_mobilephone' } },
{ field: 'title', title: 'Title', hidden: false, attributes: { "class": 'contactCell_title' } },
{ field: 'email', title: 'Email', hidden: false, attributes: { "class": 'contactCell_email' } },
{ field: 'receivereport', title: 'Receive Reports?', hidden: false, attributes: { "class": 'contactCell_receivereport' }, template: '<input type="checkbox" #= receivereport ? "checked=checked" : "" # value="" disabled="disabled" ></input>' },
{ command: "destroy", title: " ", width: "100px" }
],
sortable: {
mode: 'single',
allowUnsort: false
}
});
Then, I have two functions below. 1 is the custom editor and the other is an attempt I considered to override the text displayed in the kendo ddl.
function loadContactTypeEditor(container, options) {
var contactTypeDS = new kendo.data.DataSource({
dataType: "json",
type: "GET",
transport: {
read: "/contacts/GetAllContactTypes/"
}
});
contactTypeDS.read();
$('<input class="contactTypeDropDown" required data-text-field="roletyp_dsc" data-value-field="roletyp_pk" data-bind="value:' + options.field + '"/>').appendTo(container).kendoDropDownList({
dataTextField: "roletyp_dsc",
dataValueField: "roletyp_pk",
autoBind: false,
select: function (e) {
//if (e.sender.text() != '') {
// $('#contactGrid_active_cell').html(e.sender.text());
//}
//if (e.sender.text() != '') {
// setTimeout(function() {
// $('.contactCell_contacttype').text(e.sender.text());
// }, 1000);
//}
//options.model[options.field] = e.sender.text();
},
//dataBound: function(){
// options.model[options.field] = e.sender.text();
//},
dataSource: contactTypeDS
});
}
function textOverrideContactType(roleId) {
//need to find a match on the passed in role/contact type ID and return it's match to "mask/overwrite" the text that's there after a user selects an item in the dropdown
$.ajax({
dataType: 'json',
type: 'GET',
url: "/contacts/GetAllContactTypes/",
contentType: 'application/json; charset=utf-8',
success: function (data) {
$.each(data, function (key, val) {
if (roleId == key) {
return val;
}
});
},
failure: function (error) {
alert("Error loading contact types.");
}
});
}
To summarize: I tried a few things with no avail. What is happening, is, the DDL renders just fine, and even when the user doesn't move off of that DDL, the proper "label" shows, but when that control loses focus, it shows the data-value-field. I can't have that, I need to be able to show the data-text-field. That's why I wrote that textoverride method. But I'm trying to call it within the grid, fields's template: and it's not working. It says it doesn't recognize that function. I don't get it; it's clearly declared. What am I supposed to pass in as the parameter, it's not exactly like the demo here...a bit different, as I'm populating the DDL with another remote data source.
http://demos.telerik.com/kendo-ui/grid/editing-custom
Here's the other thing; I need that data-value-field, ID, to persist and be passed into my web api controller when it gets called. Right now, as it stands, I'm only able to get the "text" to show in the controller and not the "ID." That ID will not be available to me in the read method. The stored procs that the CRUD is hitting is completely different. My stored proc for insert and update needs to get that contacttype ID as the number.
Thanks in advance. I'm sure I'm close...