To do a record update I usually use a CRUD and a store like this:
storeId: 'storeId',
model: 'model',
pageSize: 10,
autoLoad: true,
proxy: {
type: 'ajax',
actionMethods: {
create: 'POST',
read: 'POST',
update: 'POST',
destroy: 'POST'
},
api: {
create: 'php/crud.php?action=create',
read: 'php/crud.php?action=read',
update: 'php/crud.php?action=update',
destroy: 'php/crud.php?action=destroy'
},
reader: {
type: 'json',
rootProperty: 'net',
totalProperty: 'total',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: true,
rootProperty: 'net'
}
}
Logic for the update:
var record = form.getRecord();
record.set(values);
store.sync({
success: function () {
},
failure: function () {
},
callback: function () {
},
});
Problem: just change the value of a database column: YES / NO
Instead of removing a record with 'destroy', I want to just disable it with 'update' a database table column form NO to YES.
In this case I have no form; just a delete button.
I tried without success:
store.proxy.extraParams = {
sub_case: 'change_delete_state',
id_lista: id_lista
},
store.sync({
success: function () {
},
failure: function () {
},
callback: function () {
},
});
And:
Ext.Ajax.request({
url: 'php/crud.php?action=update',
params: {
sub_case: 'change_delete_state',
id_lista: id_lista
},
success: function () {
store.commitChanges();
},
failure: function () {
},
callback: function () {
},
});
I would appreciate suggestions to solve this problem.
EDITED:
Solved like this:
api: {
destroy: 'php/crud.php?action=destroy'
},
cliente-side logic:
// soft delete
store.proxy.extraParams = {
sub_case: 'change_delete_state',
id_lista: id_lista
},
//or
// hard delete
store.proxy.extraParams = {
id_lista: id_lista
},
store.remove(record);
store.sync({...});
server-side (PHP):
case "destroy":{
$record = stripslashes($_POST['net']);
$data = json_decode($record);
$id_lista = $data->{'id_lista'};
if($_REQUEST['sub_case'] == "change_delete_state"){
$sqlQuery = "UPDATE ...";
(...)
}else{
$sqlQuery = "DELETE ...";
(...)
}
}
You are well off if you hide the database logic on the server-side as far as possible.
So, if you only have one way to get rid of a record in the front-end, and the record should be removed from the store, you would just exchange the destroy api of that one "special" store with a special api:
api: {
create: 'php/crud.php?action=create',
read: 'php/crud.php?action=read',
update: 'php/crud.php?action=update',
destroy: 'php/crud.php?action=hide' // hide the record using a SQL update, and remove it from the client-side store; don't remove from server
},
Of course you would have to insert special logic into the crud.php to do the special processing on action=hide.
If you want to have two different ways, one for a "hard delete" and one for a "soft delete", but both should be removed from the store, things become a bit more complicated. You would then need a special boolean "flag" in your record that is processed server-side.
E.g.
fields:[{
name:'hardDelete',
type:'bool',
defaultValue:false
}]
and then you would do sth. along
if(hardDelete) record.set("hardDelete",true);
store.remove(record);
store.sync(
and on the server side you would have to read that flag and act according to its value.
Related
I am trying to bind returned data from datasource to grid but the problem is that non of my data source functions is called...
transactionHistoryGridDS: new kendo.data.DataSource({
error: function () {
alert("erroe")
},
complete: function () {
alert("completed")
},
success: function () {
alert("success");
},
transport: {
read: {
dataType: "json",
type: 'POST',
url: args.TransactionHistoryUrl,
data: {
id: function () {return vm.transactionHistoryParams.id },
originBranch: function () {return vm.transactionHistoryParams.originBranch },
take: function () {return vm.transactionHistoryParams.take },
skip: function () {return vm.transactionHistoryParams.skip }
}
},
schema: {
parse: function (data) {
alert("hey...")
return data;
},
data: "data",
total: "total",
},
pageSize: 20,
serverPaging: false
}
}),
When i call read datasource through below code
vm.transactionHistoryGridDS.read();
Ajax request is called and data successfully returned from the server,but non of the functions including success and error and complete and parse is called
and consequently, data is not bind to the grid.
I can see some bugs that need to be fixed before your grid will work.
First of all, schema, pageSize, serverPaging is on wrong indent level, it should be on same level as transport not inside it.
transport: {...},
schema: {...},
serverPaging: ...,
pageSize: ...
Every grid should have dataSource property, read will be called automatically and data will be populated, you dont need to set data to grid or call read() function:
$('#grid').kendoGrid({
dataSource: {
transport: {
read: {...}
}
}
});
In your case I assume vm is a grid so you need to set dataSource:transactionHistoryGridDS, check example links below
If you need to send data with request use parameterMap:
$('#grid').kendoGrid({
resizable: true,
filterable: true,
sortable: true,
pageable: {
pageSize: 10,
refresh: true,
pageSizes: [5, 10, 20, 100, 500, 1000]
},
dataSource: {
pageSize: 10,
serverPaging: true,
serverFiltering: true,
transport: {
read: {
url: 'url',
type: 'POST',
dataType: 'JSON',
contentType: 'application/json'
},
update: {...},
destroy: {...},
parameterMap(data, type) {
switch (type) {
case 'read':
let request = {};
request.page = data.page - 1;
request.page_size = data.pageSize;
request.sort = data.sort;
request.filter = data.filter;
return JSON.stringify(request);
case 'destroy':
return kendo.stringify(data);
default:
break;
}
}
}
}
});
There is two way of geting data from kendo dataSource request, first one it with complete function that is called when request and response is finished. The second is promise on every dataSource request.
First example: complete call
Second example: promise call
This is my store MyStore.js
Ext.define('myProject.store.MyStore', {
config:{
storeId: 'MyStore',
autoLoad: false,
autoSync: false,
allowSingle: true,
clearOnPageLoad: true,
model: 'abc.model.MyStoreModel',
proxy: {
type: 'rest',
actionMethods: {create: 'POST', read: 'GET', update: 'POST', destroy: 'POST'},
url:'/services/rest/MyService/myService',
reader: {
type: 'json',
rootProperty:MyServiceView.elements.collection',
successProperty : 'success'
},
writer:
{
type: 'json',
root: 'MyServiceDataView',
nameProperty: 'mapping',
expandData : true
},
listeners: {
exception: function(proxy,response,operation){
}
}
}
}
});
This is my Model
Ext.define( 'myProject.model.MyStoreModel', {
extend: 'Ext.data.Model',
config:{
idProperty: 'keyStr',
fields:[
{
name: 'keyStr',
type: 'string',
},
{
name: 'sId',
type: 'int'
},
{
name: 'dCode',
type: 'string'
},
{
name: 'sNumber',
type: 'int'
}
]
},
});
Inside my Controller.js, I have this method
syncMyStore: function()
{
var deferred = Q.defer();
var successfulSync= 'false';
var me = this;
var myStore = Ext.getStore('MyStore');
if(this.isSyncRequires(myStore)) //assume this is always true
{
myStore.sync({
success: function () {
successfulSync = 'true';
deferred.fulfill();
}
});
}
else
{
deferred.fulfill();
}
return successfulSync;
},
Suppose I have 5 records in my store i.e record0, record2 ... record4.
For each records, it is calling the Rest Service. So total 5 Rest calls
Requirement 1: Instead of using success property, I want to perform some actions on the basis of status code.
i.e if status code is 200, then consider it success.
Requirement 2: After each rest call, I want to remove record/mark dirty as false on the basis of response status (200) for that particular record.
Means, suppose for record1 and record2 if status code is 200, then I want to remove/mark dirty=false for record 1 and record2 only.
I will be really thankful for you if you help me out with this.
Assuming that record0, record1, record3 .. have some unique way of identification. Make an ajax call for each record(REST api call ) then if the response is 200, control will hit "success" function. Then if the response has data to identify records select that record and change its dirty flag to false. In the failure function do the same and change dirty flag to true.
There are two things you need to conform to make better answer
Will you be using records as payload for your rest api call ?
Will the response have indication record, i.e i'll have guid related to
record ?
I am on an custom ajax implementation for bootstrap-table (the documentation : http://bootstrap-table.wenzhixin.net.cn/documentation/) :
For some reason, I would like to have multiple bootstrap Tables (let's call them searchTable1 , searchTable2,etc). Each of these table will be set on a custom date range (30 last days, 60 last days,etc).
I would like to pass a parameter (like the table Jquery selector or any data-myCustomDataAttribute parameter) . How can I do that ? (I tried using call but bootstrap already call it on the ajaxCallback function so It seems I cannot use it here).
It will look like stupid to make x functions that are exactly the same except for two fields depending on the table. Does someone has an idea to do that ?
Here is my code :
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: provideFeedbacksList,
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});
The ajax provider :
// I only used this example : http://issues.wenzhixin.net.cn/bootstrap-table/index.html#options/custom-ajax.html
function provideFeedbacksList(params) {
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
// retrieve the date range for this table :
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-start")
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-end")
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
Bonus, the call stack :
Finally found my answer , I have to wrapper it as a function to enable bootstrap table to pass also its data:
Self solved my issue :
js:
function callbacker(test){
console.log(test);
return function (params) {
console.log(params);
console.log(test);
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
}
html:
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: callbacker("whatEverValueYouWant"),
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});
I have a Kendo Grid that loads data via ajax with a call to server-side ASP.NET read method:
public virtual JsonResult Read(DataSourceRequest request, string anotherParam)
In my client-side JS, I trigger a read when a button is clicked:
grid.dataSource.read( { anotherParam: 'foo' });
grid.refresh();
This works as expected, only I lose the additional param when I move through the pages of results in the grid, or use the refresh icon on the grid to reload the data.
How do I persist the additional parameter data in the grid?
I have tried setting
grid.dataSource.data
directly, but without much luck. I either get an error if I pass an object, or no effect if I pass the name of a JS function that returns data.
if you want to pass additional parameters to Read ajax datasource method (server side), you may use
.DataSource(dataSource => dataSource
...
.Read(read => read.Action("Read", controllerName, new { anotherParam= "foo"}))
...
)
if you want to pass additional parameters through client scripting you may use datasource.transport.parameterMap, something as below
parameterMap: function(data, type) {
if (type == "read") {
return { request:kendo.stringify(data), anotherParam:"foo" }
}
Use the datasource.transport.parameterMap
parameterMap: function(data, type) {
if (type == "read") {
return kendo.stringify(data, anotherParam);
}
I'm not sure where your other param is coming from, but this is generally how I send extra parameters to the server.
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.parameterMap
if use datasource object :
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
data: function () {
return {
additionalParam: value
};
}
},
//parameterMap: function (data, type) {
// and so use this property to send additional param
// return $.extend({ "additionalParam": value }, data);
//}
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
and set options in grid:
$("#grid").kendoGrid({
autoBind: false,
dataSource: dataSource,
selectable: "multiple cell",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
]
});
and in click event this code :
dataSource.read();
and in api web method this action:
[HttpGet]
public HttpResponseMessage GetData([FromUri]KendoGridParams/* define class to get parameter from javascript*/ _param)
{
// use _param to filtering, paging and other actions
try
{
var result = Service.AllCustomers();
return Request.CreateResponse(HttpStatusCode.OK, new { result = result });
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { result = string.Empty });
}
}
good luck.
To persist the updated value of the additional parameter through pagination, you will need to create a global variable and save the value to it.
var anotherParamValue= "";//declare a global variable at the top. Can be assigned some default value as well instead of blank
Then, when you trigger the datasource read event, you should save the value to the global variable we created earlier.
anotherParamValue = 'foo';//save the new value to the global variable
grid.dataSource.read( { anotherParam: anotherParamValue });
grid.refresh();
Now, this is important. In your datasource object transport.read.data must be set to use a function as shown below:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
//Must be set to use a function, to pass dynamic values of the parameter
data: function () {
return {
additionalParam: anotherParamValue //get the value from the global variable
};
}
},
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
Now on every page button click, you should get the updated value of the anotherParam which is currently set to foo
I'm trying to integrate kendoGrid on a Backbone View, this is my view code:
App.Views.UsersManager = Backbone.View.extend({
tagName: 'section',
id: 'users-manager',
className: 'tile',
template: Handlebars.compile($('#profile-usersManager-template').html()),
render: function () {
console.log('usersManager.render -> collection', this.collection);
var self = this;
this.$el.html(this.template());
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data'
},
batch: true
});
this.$('table.users-manager').kendoGrid({
scrollable: false,
sortable: true,
dataSource: dataSource,
toolbar: ["save"],
editable: true,
navigatable: true,
// filterable: true,
});
return this;
}
});
The view render correctly, and the kendoGrid correctly GET my users data from my SlimPHP framework, but when i try to modify an element of the grid and hit the "Save Changes" button provided by "toolbar: ["save"]", nothing happens, even on my firebug console... there's no server communication at all.
I'm new on kendo (and Backbone also) development, maybe i'm failing something on the syntax? :stuck:
Update after Atanas Korchev answer
this is my DataSource updated:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data',
model: {
id: 'id',
fields: {
email: {},
name: {},
surname: {},
rank: {},
type: {}
}
}
},
batch: true
});
That not solve my issue, i wanna notice that my php code look like that actually:
$app->put('/users', function () use ($app, $db) {
exit('put ok');
});
Just to see if the client/server communication works... I know it will be an error, but I can't see any firebug error too, like the "Save Changes" button has no event... (I will try the Dennis Rongo suggestion.. but I dont think is the solution...)
Sorry for my bad english
Try describing your model in the DataSource settings:
schema: {
data: 'data',
model: {
id: "MyId"
}
}
You need to at least specify the id.
Solved by removing the data: 'data' from the schema object, there's the link kendoGrid batch editing!