ExtJs5: How to read server response in Model.save - extjs5

I use Model.save to save data from the ExtJs form. Sometimes server returns operation status in following format:
{"success": false, "error": {"name": "Invalid Name"}}
The following code sends data from form to server:
var model = formPanel.getRecord();
model.save({
callback: function(record, operation, success) {
// operation.response is null,
// and success === true
// how to read server response here?
}
})
Server response is treated as successful because HTTP status is 200. So I I have to read server response to check operation status. But operation.response is null in callback function.
Here is my Model:
Ext.define('My.Model', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{name: 'id', type: 'auto'},
{name: 'name', type: 'auto'}
],
proxy: {
type: 'rest',
url: 'api/v1/models',
appendId: true,
reader: {
type: 'json',
},
writer: {
type: 'json'
}
}
});
Question: how can I access server response after Model.save's call?
More generic question: is it semantically correct to use Model.load or Model.save to populate/save the ExtJs form?
I'm using ExJs 5.0.1.1255.

I created some simple test code for this:
var Clazz = Ext.define('MyModel', {
extend: 'Ext.data.Model',
proxy: {
type: 'rest',
url: 'api/v1/models'
}
});
var instance = Ext.create('MyModel', {
name: 'MyName'
});
instance.save({
callback: function(record, operation) {
}
});
The server responds with:
{
success: true,
something: 'else'
}
You can see this in a fiddle here: https://fiddle.sencha.com/#fiddle/fhi
With this code, the callback has a record argument, and record.data contains the the original record merged with the server response. In addition, you can do operation.getResponse() (rather than just operation.response) to get full access to the server's response.
In regard to your question on load vs save, if you use view models and bind the model that way, it kind of becomes moot as your form should always reflect the state of the model.

Using model.save() and Model.load() is definitely the correct thing to do.
In addition to providing a custom callback, you should investigate configuring a custom proxy. In a custom proxy, you can provide your own implementation of the extractResponseData method. This would let you centralise your need to examine the server response.

Related

How to send multiple parameters from kendo data source read operation to WebApi controller

I have the following scenario: I have a kendo.dataSource which is populated via read request to a WebApi Controller. In addition to the read, I am sending a couple of parameters, which then I use in my controller to do some server logic. I was able to send as many simple parameters as I want via the parameterMap property of the transport function. Till now it was a simple get request. However now I need to send additional json object to the controller as a parameter. I read that I have to transform the Get request to Post and put the Json onto the body of the request but I don't know how to do it.
The code that I have so far:
var gridDataSource = new kendo.data.DataSource({
type: 'odata-v4',
transport: {
read: {
url: wave.alarmsAndEvents.api('api/alarmsAndEventsSearch/post'),
type: "POST",
data: {
SearchModel: JSON.stringify(vm.searchModel)
},
contentType: 'application/json; charset=utf-8',
},
parameterMap: function (data, operation) {
if (operation === "read") {
data.startDate = kendo.toString(vm.selectedTimeInterval.start, "G");
data.endDate = kendo.toString(vm.selectedTimeInterval.end, "G");
data.alarmsToDisplay = vm.maxRecords;
}
return kendo.stringify(data);
}
},
pageSize: vm.maxRecords,
error: function (e) {
alert(e.xhr.responseText);
}
});
The SearchModel is the thing that I want to send as JSon. The rest are simple DateTime and int parameters.
My controller:
[HttpPost]
public IQueryable<AlarmsSearchViewModel> Post(DateTime startDate, DateTime endDate, int alarmsToDisplay, [FromBody]JToken jsonbody)
{
....
return something;
}
I end up with Not Found 404, but I am pretty sure that I have messed up the parameters. And from the Network window I can see that the json object is not sent at all. Any help will be much appreciated!

Not able to perform CURD operations properly in my Extjs app using Json-Server

I am using Json-server to test CURD operations in my extjs grid. I have put some dummy data on json-server and I am able to read, delete, update and edit that data.
But When I create data using my extjs app, I am not able to delete or edit that data cause auto generated Id is "nameOfMyModel + autoIncrementNumber".
My Store is:
Ext.define('ThemeApp.store.peopleStore', {
extend: 'Ext.data.Store',
model: 'ThemeApp.model.peopleModel',
storeId: 'peopleStore',
pageSize: 500,
autoLoad: true,
autoSync: true
});
Model is:
Ext.define('ThemeApp.model.peopleModel', {
extend: 'Ext.data.Model',
fields: [ 'id' ,'title','body'],
proxy: {
type: 'rest',
//format: 'json',
limitParam:"",
filterParam: "",
startParam:'',
pageParam:'',
url:'http://localhost:3000/posts',
api: {
read : 'http://localhost:3000/db',
create: 'http://localhost:3000/posts',
update : 'http://localhost:3000/posts' ,
destroy : 'http://localhost:3000/posts'
},
headers: {'Content-Type': "application/json" },
reader: {
type: 'json',
rootProperty:'posts'
},
writer: {
type: 'json'
}
}
});
And I am Adding user like:
var UserStore = Ext.getStore('peopleStore');
var user = Ext.create('ThemeApp.model.peopleModel',{title: "Test", body: "Testing" });
user.save(); //POST /users
UserStore.load();
And For Deletion:
var grid = button.up('gridpanel');
var selection = grid.getView().getSelectionModel().getSelection()[0];
if (selection) {
UserStore.remove(selection);
UserStore.load();
}
Can anyone tell me why I am not able to delete/update records which I generate via extjs app?
The Id of simple post is like
http://localhost:3000/posts/(number like 1 or 2)
and of app generated record is
http://localhost:3000/posts/ThemeApp.model.peopleModel-1
And I can see app generated record in database.json but browser is saying that this url doesn"t exist.
Kindly point out my mistake
Reason you can't delete them is because they are not created properly. First of all to generate sequential ids use
identifier: 'sequential' in your model, than it will generate numeric id's
You can read it in detail here Model identifier
After doing this generate new objects and see if you can handle them properly.

How to make a store with jsonreader using metadata in Extjs 4?

Is it possible to create a store that will read json, and use fields specified in the metadata in the json as a model?
I want to say something like:
var store = new Ext.data.Store({
autoLoad: {
params: {
metaNeeded: true
}
},
reader: new Ext.data.JsonReader({fields:[]}),
proxy: new Ext.data.HttpProxy({
api: {
url: 'php/chart-data.php'
}
})
});
I've tried a number of combinations however I cannot seem to get it to work.
I currently get the error "Cannot call method 'indexOf' of undefined". I've had others including "object has no read method".
The json I am sending is:
{
metadata:{
root:"rows",
sortInfo:{
field:"date",
direction:"ASC"
},
fields:[ {
name:"date"
}, {
name:"flow"
},{
name:"limit"
}
],
idProperty:"date"
},
success:true,
rows: << snip >>
}
Is it possible to have the store's model configured by the data that it receives, so I could use the same store later with different fields (e.g. date, flow, limit and temperature)?
I have gotten it to work with the following:
var store = new Ext.data.Store({
proxy: {
type: 'ajax',
url: 'php/chart-data2.php',
reader: new Ext.data.JsonReader({
fields:[]
})
}
});
And the php that sends the json:
'{"metaData":{
"root":"rows",
"fields": [
{"name":"date",
"type":"number",
"convert": function(val, rec) {
return val*1000
} },
{"name":"flow"},
{"name":"limit"}
]
},
"totalCount":'.count($chart).',
"success":true,
"rows":' . json_encode($chart) . '
}'
This now allows the server to specify the data (that's getting displayed in a chart), and can add in series dynamically. I don't know if it is good, but it works. I am kind of disappointed in the lack of documentation about this.

How can i load data from a json file

i use extjs and load a json file with the store loader.
I want to load a json file. It will contain "totalRecords" and i want to put this in a var. For example var Records. This way i can display it at some positions of my app and use it for alerts.
thanks to your help i know have this:
total = Ext.create('Ext.data.Store', {
model: 'step1',
proxy: {
type: 'ajax',
url: 'testevents.json',
reader: {
type: 'json',
root: 'slaevents'
}
},
listeners: {
load: function() {
records = total.getRange()
test = records[0].get('event')
alert('1 =' +test)
}
},
autoLoad:true
});
alert('2 =' +test)
This will show alert with "1 =other". That is correct. And "2 =undifined". That is wrong. How can i use the test outside of this store?
Thanks
Realize that your store doesn't load instantly so it has nothing in it when you assign it to a variable immediately afterwards in the js. You need to listen for the store to load and then assign it, or assign it in a callback. For example, this works fine:
// get the countries
var countries = Ext.create('Ext.data.Store', {
fields: ['id','name'],
proxy: {
type: 'ajax',
url: '../getCountries',
reader: 'json'
},
listeners: {
load: function() {
records = countries.getRange()
alert(records[0].get('name'))
}
}
});
This alerts "Argentina".
records becomes an array of Ext.data.Model objects each of which have all the methods that Ext.data.Model has. This is covered here in the API.

How do I get an ExtJS JsonStore to put the JSON data directly into the request body?

I have a JsonStore configured like so:
var store = new Ext.data.JsonStore({
restful: true,
url: '/categories',
remoteSort: true,
idProperty: 'Id',
totalProperty: 'total',
root: 'results',
writer: new Ext.data.JsonWriter({
encode: false
}),
fields: [ 'Id', 'Name' ]
});
I grab some data from the server, then edit one of the records. When I tell the store to save, it sends this JSON back to the server:
{
"results":
{
"Name":"Trivial123",
"Id":2
}
}
The store is wrapping the JSON inside the results property (the root property configured on the store). However, the server expects this:
{
"Name":"Trivial123",
"Id":2
}
In other words, the serialized entity should be put directly in the response body, and not wrapped in a property. Does anyone know how I can configure the store to do this?
You need to override the data rendering function in the JsonWriter, like so:
var rootlessRenderFunction = function (params, baseParams, data) {
if (this.encode === true) {
Ext.apply(params, baseParams);
params = Ext.encode(data);
} else {
params.jsonData = data;
}
};
var myWriter = new Ext.data.JsonWriter({
encode: false,
writeAllFields: true
});
myWriter.render = rootlessRenderFunction;
var myStore = new Ext.data.JsonStore({
// ... various config values ...
writer: myWriter
});
This "rootlessRenderFunction" implementation is the same as the Ext JsonWriter's render code except it doesn't interpose a root in the request data.
This is a hack, of course.
I'm assuming you can't just not set the root value for the store for some reason? That's the way I normally do it.