I have a kendo grid where the is a Start Date field. When the Start Date field is changed for a row, I need to set the value of another field in the same row to null.
I am having trouble detecting when a field is edited
I have read the Kendo UI documentation on datasource, specifically the change event section. It's clear the a change event of type "itemchange" is what I need. What I find strange is that when I change the Start Date field the only event that fires is a sync action. It may be worth noting that I have have autoSync : true set in my Datasource.
For context, here is a snip of what some of the grid looks like and the data source code. Any suggestions would be much appreciated.
var componentsDataSource = new kendo.data.DataSource({
autoSync: true,
transport: {
read: function (e) {
if ($scope.Booking.Components.length != 0) {
e.success($scope.Booking.Components);
}
else {
e.success([]);
}
},
update: function (e) {
e.success(e.data);
},
destroy: function (e) {
$scope.loadNotesForBooking();
e.success(e.data);
}
},
change: function (e) {
if (e.action === "itemchange") {
console.log("A itemchange happened");
console.log(e);
}
},
error: function (e) {
$log.error("ComponentsDataSource error:");
$log.error(e);
messageService.setError(e.xhr, "componentsDataSource.transport.error", e);
},
schema: {
model: {
id: "Id",
fields: {
Id: { editable: false, nullable: false },
ProductCode: { editable: false, nullable: false },
Name: { editable: false, nullable: false },
Status: { editable: false, nullable: false },
Description: { editable: false, nullable: false },
UnitDescription: { editable: false, nullable: false },
StartDate: { type: "date", editable: true, nullable: false },
NumberOfAdults: { type: "number", editable: true, nullable: false, validation: { min: 0, required: true } },
NumberOfChildren: { type: "number", editable: true, nullable: false, validation: { min: 0, required: true } },
NumberOfInfants: { type: "number", editable: true, nullable: false, validation: { min: 0, required: true } },
Price: { editable: false, nullable: false },
PickupLocation: { editable: true, nullable: true },
DropoffLocation: { editable: true, nullable: true }
}
},
parse: function (response) {
if (response != null) {
$.each(response, function (i, item) {
if (item != null) {
//parse the data and convert the StartDate field (which comes through as a string) to a date so it can be formatted nicely by the grid
if (item.StartDate && typeof item.StartDate === "string") {
item.StartDate = kendo.parseDate(item.StartDate);
}
//build the description of the bus stops. This is done by the busStopData source for the dropdown lists but needs to be built here for any bookings being loaded
if (item.PickupLocation) {
if (item.PickupLocation.Code != "") {
item.PickupLocation.Description = item.PickupLocation.Name + " - " + item.PickupLocation.Time;
}
else {
item.PickupLocation.Description = "";
}
}
if (item.DropoffLocation) {
if (item.DropoffLocation.Code != "") {
item.DropoffLocation.Description = item.DropoffLocation.Name + " - " + item.DropoffLocation.Time;
}
else {
item.DropoffLocation.Description = "";
}
}
//add GUID style Ids to notes. This faciliates editing/deleting them from the grid as each can be uniquely identified
if (item.Remarks) {
if (item.Remarks.length > 0) {
$.each(item.Remarks, function (i, remark) {
if (!remark.Id) {
remark.Id = guid();
}
});
}
}
}
});
}
return response;
}
}
});
Related
Here Ia m using Kendo-UI with Angular-JS.
Facing an issue while integrating Pagination (pageable) on Kendo grid table, it showing 'No items to display' even if the data (records) are loaded properly.
Not sure whats wrong with it, Any help would be appropriated...
Following is the function I am using to load/init the data grid.
function getProjectsAtAGlance() {
$scope.gridOptions = {
scrollable: false,
sortable: true,
pageable: {
pageSizes: [5, 10, 15, 20, 25, 50]
},
change: function (e) {
$scope.pageSize = $scope.gridOptions.dataSource.pageSize();
},
dataSource: {
serverPaging: true,
transport: {
read: function (options) {
$scope.options = options;
var filters = {
skip: options.data.skip,
take: options.data.take,
sortBy: $scope.sortBy,
projectGlanceIncludeArchived: $scope.includeArchivedProjects,
projectGlanceExcludeProjectsWithNoBudgets: $scope.excludeProjectsWithNoBudgets
};
$http.post("/Home/ProjectsAtAGlanceReport", filters)
.success(function (result) {
var projects = result.projects;
for (var i = 0; i < projects.length; i++) {
var project = projects[i];
project.startDate = moment(projects[i].startDate).format("L");
project.endDate = moment(projects[i].endDate).format("L");
}
options.success(projects);
})
.error(function (error) {
console.log(error);
});
}
},
pageSize: $scope.pageSize,
schema: {
total: function (respose) {
return $scope.data;
},
model: {
fields: {
name: {
editable: false,
nullable: true
},
resourceCount: {
editable: false,
nullable: true
},
clientName: {
editable: false,
nullable: true
},
startDate: {
editable: false,
nullable: true
},
endDate: {
editable: false,
nullable: true
},
projectId: {
editable: false,
nullable: true
},
projectedBudgetPercentage: {
defaultValue: 100
},
defaultValue: {
totalBudget: 0,
totalHours: 0,
burnedBudget: 0,
burnedHours: 0,
projectedBudget: 0,
projectedHours: 0,
projectedHoursPercentage: 0,
remainingBudget: 0,
remainingBudgetPercentage: 0,
remainingHours: 0,
remainingHoursPercentage: 0
}
}
}
}
},
columns: [
{
template: "<div class='name-column'>" +
"<p><a class='highlighted-blue' href='/Projects/ProjectAdmin/{{dataItem.projectId}}'>{{dataItem.name}}</a></p>" +
"<small>{{dataItem.clientName}}</small>" +
"<small ng-if=\"dataItem.startDate !== 'Invalid date'\">{{dataItem.startDate}} - {{dataItem.endDate}}</small>" +
"<small ng-if=\"dataItem.startDate === 'Invalid date'\"><i class='fa fa-exclamation-triangle text-danger'></i> Start date and end date are not defined.</small>" +
"<small>{{dataItem.resourceCount}} Resources</small></div>"
},
{
template: kendo.template($("#kendoProgressBarColumnTemplate").html())
},
{
template: "<accuracy-gauge-per-project accuracy='dataItem.accuracy'></accuracy-gauge-per-project>"
},
{
template:
"<p>{{dataItem.accuracy | percentage:0}} Accurate</p>" +
"<p>{{100-dataItem.accuracy | percentage:0}} Non Accurate</p>"
}
]
};
}
Here is an output snippets for reference.
I think the pageSize attribute needs to be declared within the dataSource like so:
dataSource: {
serverPaging: true,
transport: {... // transport options
},
pageSize: $scope.pageSize // before end of dataSource
},... // more grid stuff
And change what you are returning from schema.total to return response.total as per documentation.
I have a Kendo UI grid. In that I have two columns which contains datepicker.
I want to compare dates between those 2 columns for each row while doing inline editing. when clicked on Update, validation should fire.
I don't want to use editor template.
Here is the code which I am trying to implement.
fields: {
BusinessAreaDivisionMappingId: { type: "number", editable: false, nullable: false },
BatoDivisionMappingStatus: { type: "number", nullable: false, validation: { required: true } },
BusinessAreaHierarchyId: { type: "number", editable: false },
BusinessAreaCode: { type: "string", editable: false },
DivisionCode: { type: "string", editable: false },
ReferenceValue: { type: "string", validation: { required: true } },
StartDate: {
type: "date",
required: true,
validation: {
required: true,
dateComparisonValidation: function (element) {
alert('hi');
debugger;
var columnIndex = 0;
var grid = $("#bAPLMappingGrid").data("kendoGrid");
for (columnIndex; columnIndex < grid.columns.length; columnIndex++) {
if (grid.columns[columnIndex].field == "EndDate") {
break;
}
}
var StartDate = $(element).data("kendoDatePicker").value();
var EndDate = (new Date($(element).closest("tr").find("td:eq(" + columnIndex + ")").text()));
element.attr("data-dateComparisonValidation-msg", "Start Date Cannot be more than End Date");
if (StartDate && EndDate)
return (StartDate <= EndDate);
return true;
}
}
},
EndDate: { type: "date" },
IsDeleted: { type: "boolean", editable: false, nullable: true }
I have working on Keno UI grid and I have added a comboBox as a column in the grid which also supports autocomplete feature. Apparently, comboBox is working fine but when I type half of world and focus out of the comboBox cell then it shows undefined. I have tried to handle it on combobox change event, but it is still showing undefined value? Below is my code for combobox and grid.
function productDropDownEditor(container, options) {
$('<input id="ProductDropDown" style="width:250px;" data-bind="value:' + options.field + '"/>')
.appendTo(container).kendoComboBox({
dataSource: dataSource,
autoBind: false,
dataTextField: 'ProductName',
dataValueField: 'ProductID',
filter: "contains",
suggest: true,
index: 3,
change: function (e) {
debugger;
var cmb = this;
// selectedIndex of -1 indicates custom value
if (cmb.selectedIndex < 0) {
cmb.value(0); // or set to the first item in combobox
}
},
close: function (e) {
debugger;
var cmb = this;
}
});
And here is following code for kendo grid.
$(function () {
$("#grid").kendoGrid({
columns: [
{
field: "Products", width: "250px",
editor: productDropDownEditor,
title: "Product",
template: "#=Products.ProductName#",
attributes: {
"class": "select2_single"
}
},
{ field: "PurchasePrice", width: "150px" },
{ field: "PurchaseQuantity", width: "150px" },
{ field: "SaleRate", title: "Sale Rate", width: "150px" },
{ field: "Amount", title: "Amount", width: "150px" },
{ command: "destroy", title: "Delete", width: "110px" },
],
editable: true, // enable editing
pageable: true,
navigatable: true,
sortable: true,
editable: "incell",
toolbar: ["create"], // specify toolbar commands
edit: function (e) {
//debugger;
//// var parentItem = parentGrid.dataSource.get(e.model.PurchaseID);
////e.model.set("ShipCountry", parentItem.Country);
//if (e.model.isNew()) {
// // set the value of the model property like this
// e.model.set("PropertyName", Value);
// // for setting all fields, you can loop on
// // the grid columns names and set the field
//}
},
//editable: "inline",
dataSource: {
serverPaging: true,
requestStart: function () {
kendo.ui.progress($("#loading"), true);
},
requestEnd: function () {
kendo.ui.progress($("#loading"), false);
},
serverFiltering: true,
serverSorting: true,
batch: true,
pageSize: 3,
schema: {
data: "data",
total: "Total",
model: { // define the model of the data source. Required for validation and property types.
id: "Id",
fields: {
PurchaseID: { editable: false, nullable: true },
PurchasePrice: { nullable: true },
PurchaseQuantity: { validation: { required: true, min: 1 } },
SaleRate: { validation: { required: true, min: 1 } },
Amount: { type: "number", editable: false },
Products: {
nullable: false,
validation: { required: true},
defaultValue: {ProductID:1, ProductName:"Googo" },
//from: "Products.ProductName",
parse: function (data) {
debugger;
if (data == null) {
data = { ProductID: 1};
}
return data;
},
type: "object"
}
}
}
},
batch: true, // enable batch editing - changes will be saved when the user clicks the "Save changes" button
change: function (e) {
debugger;
if (e.action === "itemchange" && e.field !== "Amount") {
var model = e.items[0],
type = model.Type,
currentValue = model.PurchasePrice * model.PurchaseQuantity;//formulas[type](model);
if (currentValue !== model.Amount) {
model.Amount = currentValue;
$("#grid").find("tr[data-uid='" + model.uid + "'] td:eq(4)").text(currentValue);
}
//if (e.field == "Products") {
// $("#grid").find("tr[data-uid='" + model.uid + "'] td:eq(0)").text(model.Products);
//}
}
},
transport: {
read: {
url: "#Url.Action("Read", "Purchase")", //specify the URL which should return the records. This is the Read method of the HomeController.
contentType: "application/json",
type: "POST", //use HTTP POST request as by default GET is not allowed by ASP.NET MVC
},
parameterMap: function (data, operation) {
debugger;
if (operation != "read") {
// post the products so the ASP.NET DefaultModelBinder will understand them:
// data.models[0].ProductID = data.models[0].Product.ProductID;
var result = {};
// data.models[0].ProductID = $("#ProductDropDown").val();
for (var i = 0; i < data.models.length; i++) {
var purchase = data.models[i];
for (var member in purchase) {
result["purchaseDetail[" + i + "]." + member] = purchase[member];
}
}
return result;
} else {
var purchaseID = $("#hdnPurchaseId").val();
//output = '{ purchaseID: ' + purchaseID + '}';
data.purchaseID = purchaseID; // Got value from MVC view model.
return JSON.stringify(data)
}
}
}
},
}).data("kendoGrid");
I have a kendo grid with dynamic buttons, so after update I need to reload the grid to show/hide buttons, but it's not working :(
Here's my grid:
$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "/CentroCusto/Lista",
dataType: "json",
cache: false
},
update: {
url: "/CentroCusto/Salvar",
contentType: "application/json",
dataType: "json",
cache: false,
complete: function (data) {
if (data.status == 500) {
alert('Ocorreu um erro ao salvar o registro.');
}
else {
$("#grid").data("kendoGrid").dataSource.read();
}
}
},
parameterMap: function (options, operation) {
if (operation == "update") {
return { models: kendo.stringify(options) };
}
}
},
schema: {
model: {
id: "Id",
fields: {
Id: { type: "number" },
Codigo: { type: "string", editable: false },
Descricao: { type: "string", editable: false },
Empresa: { type: "string", editable: false },
AprovadorId: { type: "number", editable: false },
NomeAprovador01: { type: "string", editable: true, validation: { required: true } },
PercentualLimite: { type: "number", editable: true, validation: { required: true, max: 100 } },
Status: { type: "string", editable: false },
AprovadorN01: { defaultValue: 1, field: "AprovadorN01" },
AprovadorN02: { defaultValue: 1, field: "AprovadorN02" },
AprovadorN03: { defaultValue: 1, field: "AprovadorN03" },
AprovadorN04: { defaultValue: 1, field: "AprovadorN04" },
NomeAprovador02: { type: "string", editable: false },
Aprovador03: { type: "number", editable: true, validation: { required: false } },
NomeAprovador03: { type: "string", editable: true, validation: { required: true } },
Aprovador04: { type: "number", editable: true, validation: { required: false } },
NomeAprovador04: { type: "string", editable: true, validation: { required: true } }
}
}
},
pageSize: 20,
serverPaging: false,
serverFiltering: false,
serverSorting: false
},
height: 450,
selectable: true,
filterable: true,
sortable: true,
pageable: true,
dataBound: gridDataBound,
columns: [{ field: "Codigo", title: "Código" },
{ field: "Descricao", title: "Descrição" },
{ field: "Empresa", title: "Empresa" },
{ field: "AprovadorN01", title: "Aprovador N01", editor: aprovadorDropDown, template: "#=AprovadorN01.Nome#" },
{ field: "AprovadorN02", title: "Aprovador N02", editor: aprovador02DropDown, template: "#=AprovadorN02.Nome#" },
{ field: "AprovadorN03", title: "Aprovador N03", editor: aprovador03DropDown, template: "#=AprovadorN03.Nome#" },
{ field: "AprovadorN04", title: "Aprovador N04", editor: aprovador04DropDown, template: "#=AprovadorN04.Nome#" },
{ field: "PercentualLimite", title: "% Limite", width: "10%", format: "{0:n}" },
{ field: "Status", title: "Status", width: "10%" },
{
command: [
{
name: "edit",
text: { edit: "Ativar", update: "Salvar", cancel: "Cancelar" },
className: "btn-successo",
imageClass: 'glyphicon glyphicon-remove-circle'
},
{
name: "inativar",
text: "Inativar",
className: "btn-excluir",
click: Inativar,
imageClass: 'glyphicon glyphicon-remove-circle'
},
{
name: "edit",
text: { edit: "Alterar", update: "Salvar", cancel: "Cancelar" },
className: "btn-alterar"
}
]
, width: "180px"
}
],
editable: {
update: true,
mode: "popup"
},
cancel: function (e) {
$("#grid").data("kendoGrid").dataSource.read();
},
edit: function (e) {
e.container.kendoWindow("title", "Alterar Centro de Custo");
}
});
function gridDataBound() {
$("#grid tbody tr .btn-successo").each(function () {
var currentDataItem = $("#grid").data("kendoGrid").dataItem($(this).closest("tr"));
//Check in the current dataItem if the row is editable
if (currentDataItem.Status == "Ativo") {
$(this).remove();
}
})
$("#grid tbody tr .btn-excluir").each(function () {
var currentDataItem = $("#grid").data("kendoGrid").dataItem($(this).closest("tr"));
//Check in the current dataItem if the row is editable
if (currentDataItem.Status == "Inativo") {
$(this).remove();
}
})
$("#grid tbody tr .btn-alterar").each(function () {
var currentDataItem = $("#grid").data("kendoGrid").dataItem($(this).closest("tr"));
//Check in the current dataItem if the row is editable
if (currentDataItem.Status == "Inativo") {
$(this).remove();
}
})
if ($('#canEdit').val().toUpperCase() == "FALSE") {
$('#grid').find(".btn-alterar").hide();
$('#grid').find(".btn-successo").hide();
$('#grid').find(".btn-excluir").hide();
}
}
What happens is that when I get an error, the error message inside complete on update event is shown, but when the update succeed the instruction $("#grid").data("kendoGrid").dataSource.read() is not being called.
I would like to know if there's another way to do that, like save using $.ajax or if there's another event to call after "Update Success".
-----------------------------------------------------------------
UPDATE
I changed the 'data' to 'e' in the complete method under update and it's working now.
I'm using A Kendo Grid, With Server Side Filtering and Server Side Sorting. In my Data Source Transport Read method the field is always null. Any Suggestions?
This my code for initializing the Grid:
var gridDataSource = new kendo.data.DataSource({
transport: {
read: {
url: '#Url.Action("Read", "GridModule")',
type: 'POST',
contentType: 'application/json'
},
parameterMap: function (options) {
options.assignmentFilters = assignmentFilters;
return JSON.stringify(options);
}
},
pageSize: 20,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
schema: {
model: {
fields: {
LastSurveyDate: { type: "date" },
LastNoteDate: { type: "date" }
}
},
data: "data",
total: "totalRows"
}
});
var $grid = $('#gridAssignments');
if (e.firstLoad) {
$grid.kendoGrid({
scrollable: true,
pageable: {
refresh: true,
pageSizes: [20, 50, 100, 500, 1000],
buttonCount: 12,
messages: {
display: "Showing {0}-{1} from {2} Provider Contacts",
empty: "No Contacts Match the Filter Criteria",
itemsPerPage: "Contacts per page"
}
},
reorderable: true,
navigatable: true,
change: gridOnChange,
dataBound: gridOnDataBound,
dataSource: gridDataSource,
columnReorder: gridColumnReorder,
columnHide: gridColumnHide,
columnResize: gridColumnResize,
columnShow: gridColumnShow,
columnMenu: {
sortable: false,
messages: {
columns: "Choose columns",
filter: "Filter",
}
},
resizable: true,
height: '720px',
filterable: {
extra: false,
operators: {
string: {
contains: "Contains",
},
date: {
lt: "Is before",
gt: "Is after",
equal: "On"
}
}
},
selectable: "row",
sortable: {
mode: "single",
allowUnsort: true
},
columns: [ #Html.Raw(Model.GridColumns.Columns) ]
});
} else {
$grid.data('kendoGrid').setDataSource(gridDataSource);
}
For anyone that runs into the same problem...
In my case my code worked fine until I added two fields to the Schema.Model.Fields. Then for some reason the Field in my read method of my Grid Module was NULL. By default it all fields were treated as strings but when I added the two new properties then No default was used.
I had to add all my Grid's fields
schema: {
model: {
fields: {
LastSurveyDate: { type: "date" },
LastNoteDate: { type: "date" },
FirstName: { type: "string" },
LastName: { type: "string" },
HasNewEval: { },
HasCommitmentsToGet: { },
OnPriorityList: { type: "string" },
HasProductsBelowMinimum: { type: "HasProductsBelowMinimum" },
Points: {},
Title: { type: "string" },
Provider: { type: "string" },
Phone: { type: "string" },
TimeZone: { type: "string" },
Touches: { type: "string" },
LastNoteText: { type: "string" },
VerbalAging: { type: "string" }
}
},
That worked for me.