How to edit OndemandGrid and update to the JSONRest Store - model-view-controller

The JsonRest store I created is shown below
var questionBaseURL = "/" + contextName + "/service/questions/" + projectId + "/";
var questionStore = new dojo.store.JsonRest({
target: questionBaseURL,
handleAs: 'json',
idProperty: 'questionId'
});
questionStore = new dojo.store.Observable(questionStore);
var memoryStore = new dojo.store.Memory();
var questionCacheStore = new dojo.store.Cache(questionStore, memoryStore);
Which I use to render into the Grid created as below
var CustomGrid = declare([OnDemandGrid, Keyboard, Selection]);
var questionGrid = new CustomGrid({
store: questionCacheStore,
columns: [
editor({
label: "Questions",
field: "question",
editor: "text",
editOn: "dblclick",
sortable: true,
autoSave:true
})
],
selectionMode: "single",
cellNavigation: false
}, "questions");
questionGrid.startup();
questionGrid.renderArray(questionArray);
The data is properly populated in the grid. Now, since am using "editor", I am able edit the populated data in the grid. I am not sure how exactly to detect if the data has been edited (dirty data ) and which method to call to carry the updated data back to the server. I couldn't find any easy documentation. So any help is appreciated. Thanks in advance

You can use the grid's save method to push all items with dirty data back to the server. There is also a revert method which can be called to discard any dirty data. These are listed in the OnDemandList and OnDemandGrid documentation.
These methods are defined in dgrid/_StoreMixin which is inherited by OnDemandList (and OnDemandGrid). The editor column plugin calls updateDirty (also defined by _StoreMixin) when changes are made, which updates a dirty hash. save will check this hash and call put on the store for each dirty item.

Related

Kendo UI: Excel Export not working correctly after datasource refreshing data

I have a Grid, when users click a button, it gets some parameters and refresh datasource:
var grdUP = $("#weblogGrid").data("kendoGrid");
grdUP.dataSource.transport.options.read.url = url; // new url
//Read data source to update
grdUP.dataSource.read();
it works fine. the new data shows in the grid. And the grid has another button, which will export the data to excel. I'm using below code (also tried the built-in button):
var grid = $("#weblogGrid").data("kendoGrid");
grid.saveAsExcel();
it actually exports the data to excel file.
However, it always exports the initial data in the grid, not the data user refreshed.
For example, when the grid first shows up, it has 10 rows data. After refresh, it has 5 rows data. Now, if export, it still exports 10 rows data although the data in grid is different.
Is this a Bug? or, maybe I did something wrong in refresh grid?
Thanks
===============================
edit to clarify something
Thanks. currently, I got new data using:
var url = '/WeblogReport/GetWebLogList?fromDate=' + fromDate + '&toDate=' + toDate;
var grdUP = $("#myGrid").data("kendoGrid");
//Set url property of the grid data source
grdUP.dataSource.transport.options.read.url = url;
//Read data source to update
grdUP.dataSource.read();
So I changed to:
// get value of date
....
$.ajax({
type: "GET",
dataType: "json",
url: "/WeblogReport/GetWebLogList",
data: { FromDate: fromDate, ToDate: toDate },
success: function (data) {
alert(data);
var grid = $("#myGrid").data("kendoGrid");
grid.dataSource.data(data);
grid.refresh();
}
});
Somehow, it does not show the new data. Any suggestions?
Thank you very much.
add more clarification
Here is in the Json call.
success: function (data) {
var newdata = [{ "UserName": "username", "ClientIP": "1.1.1.1"}];
$("#myGrid").data("kendoGrid").dataSource.data(newdata);
$("#myGrid").data("kendoGrid").refresh();
//$("#myGrid").data("kendoGrid").saveAsExcel();
}
Set both of the following fields to make Excel export work:
grid.dataSource.transport.options.read.url = url;
grid.options.dataSource.transport.read.url = url;
check this:
http://jsfiddle.net/Sowjanya51/o8cw3vj8/
$('#grid1').data('kendoGrid').dataSource.data(newdata);
$('#grid1').data('kendoGrid').refresh();
You need to update the dataSource and reload the grid,otherwise the grid dataSource will still have reference to old data even though UI displays the new data.
Just set the "allPages" option on your grid to "True". like so :
excel: {
fileName: "Export.xlsx",
filterable: true,
allPages: true
},
Your original solution should be fine if you refresh the grid after you read from the data source.
var grdUP = $("#weblogGrid").data("kendoGrid");
grdUP.dataSource.transport.options.read.url = url; // new url
//Read data source to update
grdUP.dataSource.read();
//add this line to refresh the active data set in the grid
grdUP.refresh();
I had run into the same issue and this solved it for me. The only difference between your approach and mine is that you're changing the data source's read URL, whereas I was changing the data parameters for the read method. Shouldn't make any difference, but I'll mention that just in case.

Kendo Grid: Keep custom popup open after save new record

I've got a custom popup editor template for my Kendo Grid which contains tabs. One of the tabs is to have a second Kendo Grid of records relating to the record being edited.
I'd like to be able to create a new record and immediately start adding the related records, without having to re-open the newly created record. Obviously, I have to first save the record in order for its ID to be generated.
I've managed to prevent the popup editor closing when new records are saved, but I think the popup window is no longer bound to the model at this point.
Is there a way I can rebind the window to the model so I can carry on editing and adding the related records?
Thanks
Edit: Here's the technique for keeping the editor open:
The grid's edit and save events:
edit: function(e){
var editWindow = this.editable.element.data("kendoWindow");
editWindow.bind("close", onWindowEditClose);
},
save: function(e){
if (e.model.isNew()) {
preventCloseOnSave = true;
} else {
preventCloseOnSave = false;
}
}
The onWindowEditClose:
var onWindowEditClose = function(e) {'
if (preventCloseOnSave) {
e.preventDefault();
preventCloseOnSave = false;
}
};
I ended up using a slightly clunky workaround, but other than a minor UI 'flash' it works okay.
The Grid has a rowTemplate, so I've added the record's ID field to the TR tags so I can find them by ID. I then have a function that runs on the complete event when a new record is created which finds the new row and immediately opens it:
var ds = new kendo.data.DataSource({
// ...
transport: {
create: {
url: '/url/to/create',
dataType: 'json',
type: 'post',
complete: recordCreated
}
});
function recordCreated(e) {
"use strict";
var id = e.responseJSON.data[0].id,
grid = $('#grid').data("kendoGrid"),
row = grid.tbody.find("tr[data-id='" + id + "']");
grid.editRow(row);
}
On a conceptual level, you could intercept the POST action that saves the record to the database and get the saved data on return. Note that your POST action must return the saved object (as is expected). You can hook into this event by using the requestEnd method of the Kendo UI Datasource object that supports your grid and bind the saved record to your edit window (as long as you have a reference to it).
var ds = new kendo.data.DataSource({
// ...
requestEnd: function (e) {
kendo.bind(editWindow, e.response); // bind the returned data to your edit window
}
});
The understanding of the kendo ui structure (which can be tedious at times) is important to getting anything done with it. The closing of the popup that allows inserting is done in the dataBinding event. Therefore, that is the place we need to prevent it from:
$("#yourgrid").kendoGrid({
dataSource: yourDataSource,
columns: [
{ field: "YouColumn", title: "YourTitle", ... },
...
]
.
.
.
editable: "popup",
dataBinding: function(e){
//this is the key to keeping the popup open
e.preventDefault();
},
save: function (e) {
//whatever you need to do here
}
.
.
.
});
Hope this helps someone.
//Houdini

kendo ui form update cancel button

I am trying to a simple kendo ui form with 'Save' and 'Cancel' buttons. I am using the Kendo.Observable to bind the data to the form.
The functionality I am trying to achieve is, if the 'Save' button is clicked, the form data will be saved. Else, if 'Cancel' is clicked the form will come back to read-only mode with the previous data that was present. To do this, I am first saving the model data in a 'originalvalue' property on click of Update button. If 'Cancel' is clicked, the 'fields' model data is restored to the 'originalvalue'. But the issue is that the , 'originalvalue' does not contain the original value. It gets updated when the user is editing during 'Save'.
The question is - how do I retain the original model data so that it can be refreshed on cancel?
Please find below the code. Appreciate your help, thanks.
<script type="text/javascript">
var viewModel = kendo.observable ({
updated: false,
originalvalue: {},
update: function(e) {
var original = this.get("fields");
this.set("originalvalue", original);
this.set("updated", true);
},
save: function(e) {
e.preventDefault();
if (validator.validate()) {
// make an ajax call to save this data
this.set("updated", false);
}
},
cancel: function(e) {
var original = this.get("originalvalue");
validator.destroy();
this.set("fields", original);
this.set("updated", false);
},
fields: {}
});
viewModel.set("fields", formArray);
kendo.bind($("#outerForm"), viewModel);
// prepare the validator
var validator = $("#outerForm").kendoValidator().data("kendoValidator");
I had to make the exact thing on a form I am currently developing. I am using a DataSource object for the data so I had to use cancelChange().
The thing I did there:
1. I made a Datasource with a schema:
... schema: {
model: {id: "id"}}
...
2. I got the object I was editing with the mapped id:
clientDataSource.cancelChanges(clientDataSource.get(this.get("contactID")));
where the ContactID is created in a setData function where I have passed the ID:
this.set("contactID", contactID);
As I may have notices and understood, you have another problem here where you arent using a DataSource but rather data for fields?
The problem here is that your originalValue is inside the Observable object and it is referenced to the variable original and thus it has observable properties. You should have the variable originalValue defined outside the observable object:
var originalValue;
var viewModel = kendo.observable ({ ...
And you should send the formArray also to that variable so you will have the defaults load before even the observable object is loaded such as:
originalValue = formArray;
viewModel.set("fields", formArray);
So when you need to cancel it you should have:
cancel: function(e) {
var original = originalValue;
validator.destroy();
this.set("fields", original);
this.set("updated", false);
},
I havent tested it but it should provide you some guidance on how to solve that problem.

KendoUI - Remote Databinding Fails within "kendoWindow"

I made this topic once, but the information I had was a bit hard to follow and I did not get much help, so I am trying again after spending the day making a JSBIN sample.
I have a situation where I am using KendoUI to make a view model, and also to make some items within it, and when you click on sub-items that are drawn, it opens up a KendoWindow to let you edit them more specifically.
However, there is a problem with the dataSource concept, I think. When I try to bind to a dataSource on my page it works fine; But when I try to bind a kendo control to a remote datasource within a rendered window, it refuses to fetch.
If I bind only to local data, hard coded data, it works; So I know the dropdownlist is working. But I really need to be able to bind to remote data.
I have prepared a JSBIN to show this behavior (or lack thereof)
JSBIN EXAMPLE
Any help would be greatly appreciated. To see the behavior, click on the button to Create Socket Rail, then use the NumericTextBox to increase the size to any number higher than 0, then click on one of the drawn boxes.
You need to create the kendoDropDownList in the kendoWindow.activate event (or at least bind the DataSource there). Adapted from your code, this will work:
kendoWindowWidget = function (options) {
// extend the settings options so that we can take
// explicit configuration from the widget caller.
var settings = $.extend({
resizable: false,
modal: true,
viewable: true,
visible: false,
width: "450px",
height: "450px",
activate: function () {
var myDataSource = new kendo.data.DataSource({
transport: {
read: {
dataType: "json",
url: "http://jsbin.com/UYEbOXi/3/js"
}
}
});
widgets.windows.sockets.type = $('#socket-type').kendoDropDownList({
dataTextField: "Name",
dataValueField: "Id",
dataSource: myDataSource
}).data("kendoDropDownList");
}
}, options);
var $window = $("<div id='kendow-editor-window'/>")
.kendoWindow(settings)
.data("kendoWindow");
$window.databind = function (e) {
kendo.bind($window.element, e);
$window.open().center();
};
// return the created combo box
return $window;
};
Adapted JSBin (I removed a bunch of things to make it easier to manage):
http://jsbin.com/uMuFewI/3/edit

How to supply a Row ID when using jqGrid 'editGridRow' to create a new row and not the auto generated Row ID jqg1

I'm new to jqGrid, so hopefully someone can point me in the right direction.
Basically, I am using jgGrid to display a list of dates and costs that I have read in from a file that I want the user to be able to amend or add new entries or delete existing entries. Upon the user clicking an onscreen button "Apply" to post back the form , I read out the jqGrid and post back to Server in the form of a JSON string.
My problem is that when I add new rows (via 'editGridRow'), jqGrid is using it's autogenerated jqg1, jg2, jg3, etc and the new rows are being populated at the top of grid instead of at their row id position i.e at the bottom of grid.
I am able to generate RowID's as necessary, however I do not seem to be able to supply them to 'editGridRow' when creating new entries, instead it appears I have to use the keyword "new".
As you are aware the reason I am using editGridRow instead of addRowData is that editGridRow creates a modal dialog for the user to enter the data.
Any help would be appreciated.
This is what I would like to use to supply a row ID:
$("#tableGrid").jqGrid('editGridRow', gridRowID, {reloadAfterSubmit:false});
This is what I have to use to get the code to work:
$("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false});
Here is the code snippet I use for creating the gqGrid in my JSP:
var gridRowID = ${costHistoryEntries}.length
$("document").ready(function() {
$("#tableGrid").jqGrid({
data: ${costHistoryEntries},
datatype: "local",
height: 200,
colNames:['Date', 'Cost'],
colModel:[
{name:'chdate', index:'chdate', width:110, sorttype:"date", editable:true, editrules:{date:true, required:true, custom:true, custom_func:checkDate}, datefmt:'d/m/Y'},
{name:'cost', index:'cost', width:160, align:"right", sorttype:"float", editable:true, editrules:{number:true, required:true}, formatter:'float'},
],
autowidth: true,
loadonce: true,
sortname: 'chdate',
sortorder: "desc",
rowList:[10, 20, 30],
pager: jQuery('#tablePager'),
viewrecords: true,
editurl: '/myurl',
caption: "Cost History Entries" }
);
$("#tableGrid").jqGrid('navGrid', "#tablePager", {edit:true, add:true, del:true, search:true, refresh:true});
$("#addEntry").click(function() {
gridRowID++;
$("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false});
});
});
I also created a button and linked it to "addEntry" as an alternative way to adding a new row using the jqGrid Navigator "add/edit/delete/find/reload" bar. As you can see previous to loading the grid with data I stored the number of entries in gridRowID. What I was hoping to be able to do in the "#addEntry" click function was use the updated gridRowID as a RowID parameter.
As a FYI:
In a previous version of the code I was using the following to load the data into the grid:
var griddata = ${costHistoryEntries};
for (var i=0; i <= griddata.length; i++) {
$("#tableGrid").jqGrid('addRowData', i+1, griddata[i], "last");
}
but found that I could do that same with
data: ${costHistoryEntries},
Both versions correctly create row ID's for the supplied sample data from the server:
[{"chdate":"20/05/2011","cost":"0.111"},{"chdate":"01/06/2011","cost":"0.222"},{"chdate":"07/07/2011","cost":"0.333"}]
My problem is adding new rows of data.
Further update, On the server side, as a test I intercepted the post to /myurl and updated the id from "_empty" to "7" but the new entry in jqGrid still has an autogenerated jqGrid Row ID "jqg1":
Key = chdate, Value = 26/09/2011
Key = oper, Value = add
Key = cost, Value = 14
Key = id, Value = _empty
Updated Key = chdate, Value = 26/09/2011
Updated Key = oper, Value = add
Updated Key = cost, Value = 14
Updated Key = id, Value = 7
I am not quite understand your requirement. You get the input for the jqGrid from the server, but use datatype: "local" instead of the datatype: "json" for example which instruct jqGrid to get ajax request to the server to get the data whenever as needed. Moreover you want to save the date on the server, but use editurl: '/dummyurl' instead of the real server url. The editurl would get the input data from the $("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false}); and should post back the id of the new generated row. Is it not what you want?
So my suggestion would be to use some server based datatype (the bast is datatype: "json") and in the same way use real editurl which save the data on the server (in the database mostly) and place in the server response the id on the new generated data item.
UPDATED: If you use reloadAfterSubmit: false option of the editGridRow you have to use afterSubmit event handler together with reloadAfterSubmit which decode the server response and return the result in the format [true,'',new_id] For example if your server just return new rowid as the data you can use
$("#tableGrid").jqGrid('editGridRow', "new",
{
reloadAfterSubmit: false,
afterSubmit: function (response) {
return [true, '', response.responseText];
}
}
);

Resources