it is kendoui grid working against webapi (.net mvc 4 project)
the kendoGrid part in my js file:
$("#eventsgrid").kendoGrid({
dataSource: {
transport: {
read: { url: "/Webapi/V2/.../events", type: "GET" },
update: { url: "/Webapi/V2/.../events", type: "PUT" },
create: { url: "/Webapi/V2/.../events", type: "POST" },
destroy: { url: "/Webapi/V2/.../events", type: "DELETE" }
},
pageSize: 10,
schema: {
model: {
id: "eventId",
fields: {
eventId: { type: "number", editable: false, nullable: true },
eventCode: { type: "string" },
eventLocation: { type: "string" },
clientId:{ type: "string" },
startDate:{ type: "date" },
endDate: { type: "date" }
}
}
}
},
columns: [
{ field: 'eventId', title: 'ID', width: '50px', filterable: true },
{ field: 'eventCode', title: 'Code', width: '80px', filterable: true },
{ field: 'eventLocation', title: 'Location', width: '150px', filterable: true },
{ field: 'clientId', title: 'Client', width: '80px', filterable: true },
{ field: 'startDate', title: 'Start', width: '80px', format: "{0:MM/dd/yyyy}", filterable: { ui: "datepicker" } },
{ field: 'endDate', title: 'End', width: '80px', format: "{0:MM/dd/yyyy}", filterable: { ui: "datepicker" } },
{ command: [{ id: "edit", name: "edit", text: "Edit" }, { id: "destroy", name: "destroy", text: "Delete", width: "30px" }, { text: 'Details', click: gotouser }], title: " ", width: "240px" }
],
sortable: true,
editable: "popup",
filterable: {
extra: false,
operators: {
string: {
startswith: "Starts with",
eq: "Is equal to",
neq: "Is not equal to"
}
}
},
toolbar: [{ name: "create", text: "Add new Event" }],
pageable: { pageSizes: true | [10, 20, 30] }
});
the problem is: when i edit a record, or post a new one, the value i receive in my mvc controller for any of the date fields, is null.
when i check in my chrome tools, see what the grid sends to the controller (when you hit update in the popup), like this:
clientId: 1
startDate: Tue Jan 20 2015 00:00:00 GMT-0500 (Eastern Standard Time)
endDate: Thu Jan 22 2015 00:00:00 GMT-0500 (Eastern Standard Time)
logo: abcsd.jpg
featured: 4
obviously the date format is wrong, and i suppose that is why the controller does not see it as a date, the conversion/binding fails, and it gives me null.
How do i make it send a different format, like mm/dd/yyyy ? isn't that covered by the format definitions in the columns array?
You can try to use parameterMap function. Look at kendo parameterMap documentation.
Similar to this:
parameterMap: function (data, operation) {
if (operation != "read") {
var parsedDate = kendo.parseDate(data.startDate, "MM/dd/yyyy");;
data.startDate = parsedDate;
return data;
}
}
For kendo parsing dates look at kendo parseDate
in the parameterMap use:
var parsedDate = kendo.toString(data.startDate, "MM/dd/yyyy")
the kendo.parseDate function takes a string as a parameter
OK, I followed Dmitriy's line, and was able to make it work. so for future generations, here is what you need to add to your js:
update: {
url: "/Webapi/..../events",
dataType: "json",
type: "PUT",
data: function (data) {
data.startDate = kendo.toString(data.startDate, "yyyy-MM-dd");
data.endDate = kendo.toString(data.endDate, "yyyy-MM-dd");
// repeat for all your date fields
return data;
}
},
// same thing for your 'create'.
// Sorry, look like a bit of 'Repeat yourself', but at least it's working.
So again, big thanks to Dimitriy!
Related
I am using the Kendo Gantt chart with ASP.NET Core MVC, and I would like to get the Day view timeline to show in 30 minute increments vs. 1 hour increments. The working hours I'm trying to display for each day are 7:00 AM to 3:30 PM, but I cannot get that 3:30 PM end of day to display.
Here is an example of getting a time header template using the jquery kendo gantt chart
<div id="gantt"></div>
<script>
$("#gantt").kendoGantt({
dataSource: [{
id: 1,
orderId: 0,
parentId: null,
title: "Task1",
start: new Date("2014/6/17 9:00"),
end: new Date("2014/6/17 11:00")
}],
views: [
{ type: "day", timeHeaderTemplate: kendo.template("#=kendo.toString(start, 'T')#") },
{ type: "week" },
{ type: "month" }
]
});
</script>
However, I can't figure out how get that template to show the 30 minute increments, or if there is a different way to accomplish this. Essentially, I want it to look like the Kendo Scheduler Timeline view shown here:
I opened a support ticket with Telerik and got an answer that while there is no built-in way to do this with the Gantt component, one way to implement would be to create a custom view as demonstrated here: https://docs.telerik.com/kendo-ui/controls/scheduling/gantt/how-to/creating-custom-view
Custom view example code:
<div id="gantt"></div>
<script type="text/javascript">
var gantt;
$(function StartingPoint() {
kendo.ui.GanttCustomView = kendo.ui.GanttView.extend({
name: "custom",
options: {
yearHeaderTemplate: kendo.template("#=kendo.toString(start, 'yyyy')#"),
quarterHeaderTemplate: kendo.template("# return ['Q1', 'Q2', 'Q3', 'Q4'][start.getMonth() / 3] #"),
monthHeaderTemplate: kendo.template("#=kendo.toString(start, 'MMM')#")
},
range: function(range) {
this.start = new Date("01/01/2013");
this.end = new Date("01/01/2016");
},
_generateSlots: function(incrementCallback, span) {
var slots = [];
var slotStart = new Date(this.start);
var slotEnd;
while (slotStart < this.end) {
slotEnd = new Date(slotStart);
incrementCallback(slotEnd);
slots.push({ start: slotStart, end: slotEnd, span: span });
slotStart = slotEnd;
}
return slots;
},
_createSlots: function() {
var slots = [];
slots.push(this._generateSlots(function(date) { date.setFullYear(date.getFullYear() + 1); }, 12));
slots.push(this._generateSlots(function(date) { date.setMonth(date.getMonth() + 3); }, 3));
slots.push(this._generateSlots(function(date) { date.setMonth(date.getMonth() + 1); }, 1));
return slots;
},
_layout: function() {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.yearHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.quarterHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[2], kendo.template(options.monthHeaderTemplate)));
return rows;
}
});
gantt = new kendo.ui.Gantt($("#gantt"),
$.extend({
columns: [
{ field: "id", title: "ID", sortable: true, editable: false, width: 30 },
{ field: "title", title: "Title", sortable: true, editable: true, width: 100 },
{ field: "start", title: "Start Time", sortable: true, editable: true, format: "{0:MM/dd/yyyy HH:mm}", width: 100 },
{ field: "end", title: "End Time", sortable: true, editable: true, format: "{0:MM/dd/yyyy HH:mm}", width: 100 }
],
views: [
"week",
{ type: "kendo.ui.GanttCustomView", title: "Quaterly", selected: true }
],
listWidth: 500,
dataBound: function() {
var height = this.timeline.view().header.height();
this.list.thead.find('tr').css('height',height);
},
dataSource: {
data: [{ id: 1, parentId: null, percentComplete: 0.2, orderId: 0, title: "foo", start: new Date("05/05/2014 09:00"), end: new Date("06/06/2014 10:00") },
{ id: 2, parentId: null, percentComplete: 0.4, orderId: 1, title: "bar", start: new Date("07/06/2014 12:00"), end: new Date("08/07/2014 13:00") }]
},
dependencies: {
data: [
{ id: 1, predecessorId: 1, successorId: 2, type: 1 }
]
}
}, {})
);
});
</script>
I have simple kendo UI grid
$("#Grid").kendoGrid({
dataSource: {
serverPaging: true,
transport: {
read: "Course/Read",
dataType: "json"
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
pageSize: 10
},
pageable: true,
columns:
[
{ field: "CourseName", title: "Name", width: 100 },
{ field: "SpecialtyName", title: "Specialty", width: 100, filterable: false },
{ title: "Edit", template: '<span class="EditIcon"><i data-bind="click:Edit(#: Id#)" class="fa fa-edit"></i></span>', width: 50 },
]
});
the problem is when I am using:
data-bind="click:Edit(#: Id#)"
when click on edit calling function not work inside kendo grid notice that both the grid and function inside knockout viewmodel
function viewmodel() {
var self = this;
self.Load = function () {
$("#Grid").kendoGrid({
dataSource: {
type: "aspnetmvc-ajax",
serverPaging: true,
transport: {
read: "Course/Read",
dataType: "json"
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
pageSize: 10
},
pageable: true,
columns:
[
{ field: "CourseName", title: "Name", width: 100 },
{ field: "SpecialtyName", title: "Specialty", width: 100, filterable: false },
{ title: "Edit", template: '<span class="EditIcon"><i data-bind="click:Edit(#: Id#)" class="fa fa-edit"></i></span>', width: 50 },
]
});
}
self.Load();
self.Edit= function (Id) {
////////my code////////
}
}
everything work fine the binding retrieve data, extra except call knockout method inside kendo grid, appreciate any help thanks.
if anyone looking for answer or open this post, this is not related to kendo, this is because the grid render rows after knockout binding done, so you can take viewmodel object in temp var in javascript and use it like tempvar.callfunction().
I cannot bind results from search in kendo grid. I've tried many times, I'm in trouble four days, I don't know what is wrong here,
When i debug action everything is working perfect,data is OK, return grid result are OK, but results aren't shown in kendo.
Here is my code:
<script>
$(function() {
$("a.k-button").on('click', function (e) {
debugger;
e.preventDefault();
var dataObj = serializeByFieldsWrap(".invoiceForm");
var dataUrl = $(this).data('url');
// dataObj.ToolboxId = toolboxId;
$('body').css('cursor', 'wait');
var result = $.ajax({
type: "POST",
url: dataUrl,
dataType: 'json',
data: dataObj,
//complete: $("#invoices-grid").data("kendoGrid").data.read(),
});
result.done(function (data) {
console.log(data);
var grid = $('#invoices-grid').data("kendoGrid");
grid.dataSource.data(data);
});
result.fail(function (error) {
console.log(error);
});
});
});
</script>
Controller:
public ActionResult List(DataSourceRequest command, FinanceListModel model)
{
var searchString = model.SearchJobItemNumber;
var isChecked = model.IsChecked;
var invoices = _invoiceService.GetAllInvoices(searchString, isChecked);
var gridModel = new DataSourceResult
{
Data = invoices.Select(x => {
var jobModel = x.ToModel();
return jobModel;
}),
Total = invoices.TotalCount
};
return Json(gridModel, "application/json", JsonRequestBehavior.AllowGet);
}
Kendo UI Grid:
<script>
$(function() {
$("#invoices-grid").kendoGrid({
dataSource: {
data: #Html.Raw(JsonConvert.SerializeObject(Model.Invoices)),
schema: {
model: {
fields: {
JobNumber: { type: "string" },
CustomerName: { type: "string" },
DepartmentName: { type: "string" },
DateInvoice: { type: "string" },
ValidDays: { type: "number" },
Delivery: { type: "string" },
IsPayed: { type: "boolean" },
Payed: { type: "number" },
Status: { type: "boolean" },
},
error: function(e) {
display_kendoui_grid_error(e);
// Cancel the changes
this.cancelChanges();
},
pageSize: 20,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
dataBound: function () {
var row = this.element.find('tbody tr:first');
this.select(row);
},
columns: [
#*{
field: "Status",
title: "#T("gp.Jobs.Fields.Status")",
template: '#= Status #'
},*#
{
field: "JobNumber",
title: "#T("gp.Invoice.Fields.JobNumber")",
template: '#= JobNumber #'
},
{
field: "CustomerName",
title: "#T("gp.Invoice.Fields.CustomerName")",
template: '#= CustomerName #'
},
{
field: "DepartmentName",
title: "#T("gp.Invoice.Fields.DepartmentName")",
template: '#= DepartmentName #'
},
{
field: "DateInvoice",
title: "#T("gp.Invoice.Fields.DateInvoice")",
template: '#= DateInvoice #'
},
{
field: "ValidDays",
title: "#T("gp.Invoice.Fields.ValidDays")",
template: '#= ValidDays #'
},
{
field: "Delivery",
title: "#T("gp.Invoice.Fields.Delivery")",
template: '#= Delivery #'
},
{
field: "Payed",
title: "#T("gp.Invoice.Fields.IsPayed")",
template: '#= (Payed == 2) ? "Комп." : ((Payed == 1) ? "ДЕ" : "НЕ") #'
},
{
field: "Id",
title: "#T("Common.Edit")",
width: 100,
template: '#T("Common.Edit")'
}
],
pageable: {
refresh: true,
pageSizes: [5, 10, 20, 50]
},
editable: {
confirmation: false,
mode: "popup"
},
scrollable: false,
selectable: true,
change: function(e) {
var selectedRows = this.select();
var jobId = parseInt($(selectedRows).data('job-id'));
var jobItemId = parseInt($(selectedRows).data('job-item-id'));
var result = $.get("#Url.Action("SideDetails", "Production")/" + jobItemId);
result.done(function(data) {
if (data) {
$(".job-edit .jobItemDetails").html(data);
}
});
},
rowTemplate: kendo.template($("#invoiceRowTemplate").html()),
});
});
</script>
DataSourceResult formats your server response like this:
{
Data: [ {JobNumber: "...", FieldName: "bar", ... } ],
Total: 100
}
In other words, the data items array is assigned to a Data field, and the total items count is assigned to a Total field. The Kendo UI DataSource configuration must take this into account by setting schema.data and schema.total:
http://docs.telerik.com/kendo-ui/framework/datasource/crud#schema
http://docs.telerik.com/kendo-ui/framework/datasource/crud#read-remote
schema: {
data: "Data",
total: "Total"
}
i have a newbie question, but i’m scratching my head on this one. I have a grid, bound to a dataadapter. On the grid, paging and filtering is explicit disabled, but the GET-call from the dataadapter allways includes following parameters in the GET-url:
?filterscount=0&groupscount=0&pagenum=0&pagesize=10&recordstartindex=0&recordendindex=18&_=1386768031615
I want to get all data, then cache it clientside for paging and filtering, but in the first step i just want to get my data bound to the grid.
Here’s my code:
var source = {
type: "GET",
datatype: "json",
datafields: [
{ name: 'url' },
{ name: 'category', type: 'int' },
{ name: 'info' },
{ name: 'status', type: 'bool' }
],
url: '/api/redirects/Getallredirects',
id: 'id'
};
var dataAdapter = new $.jqx.dataAdapter(source, {
contentType: 'application/json; charset=utf-8',
loadError: function (xhr, status, error) {
alert(error);
},
downloadComplete: function (data) {
var returnData = {};
returnData.records = data.d;
return returnData;
}
});
$("#jqxgrid").jqxGrid({
source: dataAdapter,
filterable: false,
pageable: false,
virtualmode: false,
columns: [
{ text: 'URL', dataField: 'url', width: 100 },
{ text: 'Category', dataField: 'category', width: 100 },
{ text: 'Info', dataField: 'info', width: 180 },
{ text: 'Status', dataField: 'status', width: 80, cellsalign: 'right' },
]
});
I don’t get any data, the GET-call fails because of the automatically included parameters. How do i get rid of these parameters?
I just found in the jqxGrid documentation a reference to these parameters, but no example, how to remove them:
http://www.jqwidgets.com/jquery-widgets-documentation/documentation/jqxgrid/jquery-grid-extra-http-variables.htm
Thanks in advance for any help.
The below will remove the default parameters:
var dataAdapter = new $.jqx.dataAdapter(source,
{
formatData: function (data) {
return {};
}
}
);
I am using the free Kendo web controls. I have used the grid view in several places before and decided to use the popup style editing for my current project.
I have most of it working. I have three combo boxes for category, bank account and payee and when I edit an existing item, the model object passed back to my MVC action has the correct values in it. However, when I click on the create button, the three combo box values are returned as null to the controller.
Here is the CSHTML code for this view:
#using System
#using System.Linq
#{
ViewBag.Title = "Transactions";
}
#section Head
{
<link href="~/Content/kendo/kendo.common.min.css" rel="stylesheet" />
<link href="~/Content/kendo/kendo.default.min.css" rel="stylesheet" />
<script src="~/Scripts/kendo/kendo.web.min.js"> </script>
}
#section featured
{
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>#ViewBag.Title</h1>
</hgroup>
</div>
</section>
}
<div id="grid"></div>
<script>
$(function() {
$("#grid").kendoGrid({
height: 350,
toolbar: [{ name: "create", text: "Create New Transaction" }],
columns:
[
{ field: "Date", width: "100px", template: '#= kendo.toString(Date,"MM/dd/yyyy") #' },
{ field: "Amount", format: "{0:c}", width: "100px" },
{ field: "Category", width: "80px", editor: categoryDropDownEditor, template: "#=Category.Name#" },
{ field: "BankAccount", title: "Account", width: "80px", editor: bankAccountDropDownEditor, template: "#=BankAccount.Name#" },
{ field: "Payee", width: "80px", editor: payeeDropDownEditor, template: "#=Payee.Name#" },
{ command: ["edit", "destroy"], title: " ", width: "160px" }
],
editable: { mode: "popup", confirmation: "Are you sure you want to delete this transaction?" },
pageable:
{
refresh: true,
pageSizes: true
},
sortable: true,
filterable: false,
dataSource:
{
serverPaging: true,
serverFiltering: true,
serverSorting: true,
pageSize: 7,
schema:
{
data: "Data",
total: "Total",
model:
{
id: "Id",
fields:
{
Id: { editable: false, nullable: true },
Date: { type: "Date" },
Amount: { type: "number", validation: { required: true, min: 0 } },
Category: { validation: { required: true } },
BankAccount: { validation: { required: true } },
Payee: { validation: { required: true } },
Note: { validation: { required: false } }
}
}
},
batch: false,
transport:
{
create:
{
url: "#Url.Action("Create", "Transaction")",
contentType: "application/json",
type: "POST"
},
read:
{
url: "#Url.Action("Read", "Transaction")",
contentType: "application/json",
type: "POST"
},
update:
{
url: "#Url.Action("Update", "Transaction")",
contentType: "application/json",
type: "POST"
},
destroy:
{
url: "#Url.Action("Delete", "Transaction")",
contentType: "application/json",
type: "POST"
},
parameterMap: function(data)
{
return JSON.stringify(data);
}
}
}
});
function categoryDropDownEditor(container, options)
{
$('<input required data-text-field="Name" data-value-field="Id" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList(
{
autoBind: true,
dataValueFileld: "Id",
dataTextField: "Name",
dataSource:
{
type: "json",
transport: { read: "#Url.Action("GetCategories", "Transaction")" }
}
});
}
function bankAccountDropDownEditor(container, options)
{
$('<input required data-text-field="Name" data-value-field="Id" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList(
{
autoBind: true,
dataValueFileld: "Id",
dataTextField: "Name",
dataSource:
{
type: "json",
transport: { read: "#Url.Action("GetBankAccounts", "Transaction")" }
}
});
}
function payeeDropDownEditor(container, options)
{
$('<input required data-text-field="Name" data-value-field="Id" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList(
{
autoBind: true,
dataValueFileld: "Id",
dataTextField: "Name",
dataSource:
{
type: "json",
transport: { read: "#Url.Action("GetPayees", "Transaction")" }
}
});
}
});
</script>
The binding to the kendo combo box must be working, otherwise the edit would fail as well. All I can think is that the object is not created correctly. Also, it selects the first item in the combo box by default, but even so, does not bind the value.
Following is the code for my create and update actions:
[HttpPost]
public ActionResult Create(TransactionModel transactionModel)
{
var transaction = _moneyBO.CreateTransaction();
Mapper.Map(transactionModel, transaction);
_moneyBO.UpdateTransaction(transaction);
return Json(Mapper.Map<TransactionModel>(transaction));
}
public ActionResult Update(TransactionModel transactionModel)
{
var transaction = _moneyBO.Transactions.SingleOrDefault(x => x.Id == transactionModel.Id);
if (transaction == null)
return View("NotFound");
Mapper.Map(transactionModel, transaction);
_moneyBO.UpdateTransaction(transaction);
return Json(Mapper.Map<TransactionModel>(transaction));
}
I have not found a good example using the popup custom edit. The example on the Kendo site works inline, but if you change the example to popup it does not work.
I have a same problem. Write, if you solve it, please
I found, that Kendo think that "null" (default for int?) is ObservableObject (while initialization of ComboBox), thats why it can't be parsed to "number". If you edit item (not create), value id not "null" and model bindind work's fine
Not sure if it's the only issue here but in your code example it looks like the initialization of your dropdown isn't quite correct. You have written dataValueFileld which should be dataValueField
kendoDropDownList({
autoBind: true,
dataValueFileld: "Id", <-- Incorrect spelling
dataTextField: "Name",
dataSource:
{
type: "json",
transport: { read: "#Url.Action("GetPayees", "Transaction")" }
}
});