I am working with Extjs4.1 MVC. What I am trying to do is save some data to the server but I do not know the proper format or how I should go about submitting the data to the server.
Here is what I am thinking but I do not believe the Ajax call should be in the controller, it should be in the model or in the store file?
method in my controller:
submit: function(value) {
data = {"id": 100, "tdt": "rTk", "val": "445"} // test data
Ext.Ajax.request({
url: 'http://test.myloc.com/providerSvc/dbproxy.php',
params: {
'do':'insert',
'object': 'stk',
'values': data
},
success: function(response){
alert('response.responseText);
}
})
}
My store:
Ext.define('STK.store.Stack', {
extend: 'Ext.data.Store',
model: 'STK.model.Stack',
autoLoad: true,
proxy: {
type: 'ajax',
api: {
read: 'http://test.myLoc.com/providerSvc/dbproxy.php?do=get&object=stack'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json'
}
}
});
my model:
Ext.define('STK.model.Stack', {
extend: 'Ext.data.Model',
fields: ['id', 'tdt', 'val']
});
store.sync() works only when the endpoints for GET and POST are same.
What you can do is, for GET,
set the extraParams by concatenating to the URL or by creating an object like
extraParams[urlKeys] = paramObject[urlKeys];
store.getProxy().setExtraParams(extraParams);
then,
Store.getProxy().setUrl(StoreUrlForGET);
Store.load({
callback : function(rec, operation, success) {
if (success) {}
else {}
});
and for POST write an AJAX request as,
Ext.Ajax.request({
url : StoreURLForPOST,
method : 'POST',
jsonData : Ext.JSON.encode(YourPostData),
success : function(response, request) {},
failure : function(response, request) {}
});
for this AJAX request you can,
Ext.Ajax.setDefaultHeaders({
"TokenId" : TokenValue
});
All of this code goes into your controller.
I think the store is the proper place to make the ajax call.
You can "save" one record by adding it to the store, and then calling the "sync()" function.
Something like this (beware: code not tested):
var store = Ext.create("STK.store.Stack");
var record = Ext.create("STK.model.Stack");
record.set(xvalues);
record.isDirty = true;
record.setDirty(true); // I don't know if this line is required
store.add(record);
store.sync({
success: function(batch, options){
alert("OK!")
},
failure: function(batch, options){
alert("failure!")
}
});
Related
To add query parameters to a url using jQuery AJAX, you do this:
$.ajax({
url: 'www.some.url',
method: 'GET',
data: {
param1: 'val1'
}
)}
Which results in a url like www.some.url?param1=val1
How do I do the same when the method is POST? When that is the case, data no longer gets appended as query parameters - it instead makes up the body of the request.
I know that I could manually append the params to the url manually before the ajax request, but I just have this nagging feeling that I'm missing some obvious way to do this that is shorter than the ~5 lines I'll need to execute before the ajax call.
jQuery.param() allows you to serialize the properties of an object as a query string, which you could append to the URL yourself:
$.ajax({
url: 'http://www.example.com?' + $.param({ paramInQuery: 1 }),
method: 'POST',
data: {
paramInBody: 2
}
});
Thank you #Ates Goral for the jQuery.ajaxPrefilter() tip. My problem was I could not change the url because it was bound to kendoGrid and the backend web API didn't support kendoGrid's server paging options (i.e. page, pageSize, skip and take). Furthermore, the backend paging options had to be query parameters of a different name. So had to put a property in data to trigger the prefiltering.
var grid = $('#grid').kendoGrid({
// options here...
dataSource: {
transport: {
read: {
url: url,
contentType: 'application/json',
dataType: 'json',
type: httpRequestType,
beforeSend: authentication.beforeSend,
data: function(data) {
// added preFilterMe property
if (httpRequestType === 'POST') {
return {
preFilterMe: true,
parameters: parameters,
page: data.page,
itemsPerPage: data.pageSize,
};
}
return {
page: data.page,
itemsPerPage: data.pageSize,
};
},
},
},
},
});
As you can see, the transport.read options are the same options for jQuery.ajax(). And in the prefiltering bit:
$.ajaxPrefilter(function(options, originalOptions, xhr) {
// only mess with POST request as GET requests automatically
// put the data as query parameters
if (originalOptions.type === 'POST' && originalOptions.data.preFilterMe) {
options.url = options.url + '?page=' + originalOptions.data.page
+ '&itemsPerPage=' + originalOptions.data.itemsPerPage;
if (originalOptions.data.parameters.length > 0) {
options.data = JSON.stringify(originalOptions.data.parameters);
}
}
});
I have the following code (jQuery) to create a json file:
$( ".save" ).on("click", function(){
var items=[];
$("tr.data").each(function() {
var item = {
item.Code : $(this).find('td:nth-child(1) span').html(),
itemQuantity : $(this).find('td:nth-child(4) span').html()
};
items.push(item);
});
});
Now this is my AJAX function:
(function() {
$.ajax({
url : "",
type: "POST",
data:{ //I need my items object, how do I send it to backend server (django)??
calltype:'save'},
dataType: "application/json", // datatype being sent
success : function(jsondata) {
//do something
},
error : function() {
//do something
}
});
}());
Now, my doubt is how do I send the 'item[]' object that I created to the backend? I do need to send both the item[] object and the variable 'calltype' which signals what made the AJAX call, as I have the same Django View (its the Controller equivalent for Django) in the backend being called by different AJAX functions.
How will my AJAX function look like?
Hey guys just got my answer right.
I used the following ajax function to get it right:
(function() {
$.ajax({
url : "",
type: "POST",
data:{ bill_details: items,
calltype: 'save',
'csrfmiddlewaretoken': csrf_token},
dataType: 'json',
// handle a successful response
success : function(jsondata) {
console.log(jsondata); // log the returned json to the console
alert(jsondata['name']);
},
// handle a non-successful response
error : function() {
console.log("Error"); // provide a bit more info about the error to the console
}
});
}());
So, this is sort of a self answer!!! :) Thanks a lot SO!!
I have a grid with a store which is loaded when app is launched. I have a form also to which the grid is bound to. Initially, the grid shows all records. The search form allows user to filter records. The initial load and search URLs are different. When search is clicked, I dynamically change the URL configured on the store proxy to the filter URL, pass in the form values as extraParams, and load the store. I see the request is made and a response is returned. However, my grid records dont refresh.
//grid store inside initComponent
this.store = Ext.create("Ext.data.Store",{
fields:["rptid", "text", "value", "date_created", "created_by", "active],
autoLoad:true,
proxy:{
type:"ajax",
url:"./getRpts.html",
reader:{
type:"json",
root:"data"
}
}
});
//handler for search form button
this.getRPTGrid().getStore().getProxy().url = "./getFilteredReports.html";
this.getRPTGrid().getStore().getProxy().extraParams =
this.getSearchForm().getValues();
this.getRPTGrid().getStore().load();
thats it. I confirm the request is being made to load the store and confirm the response being received in debugger. The JSON response also contains the "data" root so thats not the issue and the fields dont change either. I have done this 10,000 times before but have never experienced this. Anyone have any ideas?
I even compared the Request and Response Headers from both requests and their exactly the same minus the url and params..
Try using reload to ensure your store data.
This code below check my data after add or update, so if i add record it's automatically reload my store and select the new record.
var store = this.getRPTGrid().getStore();
Ext.Ajax.request({
method: 'POST',
url: "./getFilteredReports.html",
params: {
data: this.getSearchForm().getValues()
},
success: function(response) {
store.reload({
callback: function() {
var newRecordIndex = store.findBy(
function(record, id) {
if (record.get(
'rptid'
) === values.rptid) {
return true;
}
return false;
});
getRPTGrid.getSelectionModel().select(
newRecordIndex);
}
});
}
});
and if you want to change proxy url to update your store try to update the proxy in your model instead in your store, like this below :
Ext.define('APP.model.m_gis', {
extend: 'Ext.data.Model',
alias: 'widget.gisModel',
proxy: {
type: 'jsonp',
url: './getRpts.html',
reader: {
type: 'json',
root: 'data',
totalProperty: 'totalCount'
}
},
fields: ["rptid", "text", "value", "date_created", "created_by",
"active"
]
});
This is the store look like :
Ext.define('APP.store.s_gis', {
extend: 'Ext.data.Store',
alias: 'widget.gisStore',
model: 'APP.model.m_gis'
});
and change your proxy like you want :
var place_store = Ext.create('APP.store.s_gis');
place_store.getProxy().setExtraParam('url', "./getFilteredReports.html");
I'm trying to persist grid updates to database, so I write in my controller:
//...
editUser: function(button, eventObj) {
var view = Ext.widget('useredit');
view.down('form').loadRecord(this.getSelected());
},
getSelected: function() {
var grid = this.getUserList();
var selectedRecord = grid.getSelectionModel().getSelection()[0];
return selectedRecord;
},
updateUser: function(button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
form.updateRecord();
win.close();
this.getUsersStore().sync();
}
});
And this is my store code:
Ext.define('MyApp.store.Users', {
extend: 'Ext.data.Store',
model: 'MyApp.model.User',
autoLoad: true,
proxy: {
type: 'ajax',
actionMethods:
{create: 'POST', read: 'GET', update: 'POST', destroy: 'POST'},
api: {
create: 'data/createUser.php',
read: 'data/getUsers.php',
update: 'data/updateUser.php',
destroy: 'data/deleteUser.php'
},
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
});
When I hit "save" button firebug tells me that POST request has been sent to my php file, but when I
print_r($_POST) in php it shows me an empty array. How can this be?
By default, the proxy's writer will send the JSON string as raw POST data to the server. PHP's $_POST superglobal takes variables/parameters from the raw POST data, if possible, e.g. if it contains url-encoded data:
var1=a&var2=b&var3=c
However, since your POST data is just a JSON string, there are no key=value pairs to extract from, which is why your $_POST array is empty.
To read the raw post data, you can use PHP's input stream php://input:
$json = file_get_contents('php://input');
$data = json_decode($json);
var_dump($data);
Alternatively, in ExtJS you can also tell the writer to pass the JSON string as a HTTP parameter to the request using the encode and root configurations:
proxy: {
// ...
writer: {
type: 'json',
encode: true,
root: 'users'
}
}
Which will result in the writer generating the POST data like this:
users={"var1":"a","var2":"b","var3":"c"}
and therefore allows you to use the $_POST variable in PHP:
$data = json_decode($_POST['users']);
var_dump($data);
I've a ScriptTagProxy and I'm able to receive the data, but now I wanted to update a record. I've specified an url but only one url. Do I have to handle all the actions (read, update, create, delete) with this url?
If yes: how does the action is applied to the url?
If not: how I can specify more urls?
Here is the code I have so far:
app.stores.entries = new Ext.data.Store({
model: "app.models.Entry",
storeId: 'app.stores.entries',
proxy: {
type: 'scripttag',
url: 'http://myurl.de/getEntries.php',
extraParams: {
username: Ext.util.JSON.decode(window.localStorage.getItem('settings')).username,
password: Ext.util.JSON.decode(window.localStorage.getItem('settings')).password
},
reader: {
type: 'json'
},
writer: {
type: 'json'
}
}
});
I've read in the docs that you can pass an config object to the save function of a model to configurate the proxy.
So I tried following:
entry.save({
url: 'http://mysite.com/updateEntry.php',
extraParams: {
username: Ext.util.JSON.decode(window.localStorage.getItem('settings')).username,
password: Ext.util.JSON.decode(window.localStorage.getItem('settings')).password,
entry: entry
},}
As you see there is a url specified.
But I still get the error:
Uncaught Error: You are using a ServerProxy but have not supplied it with a url.
);
Same behaviour when using AjaxProxy or RestProxy for example :(
Hering,
With your first block of code you ask:
Question 1) "Do I have to handle all the actions (read, update, create, delete) with this url?"
The answer is yes.
Question 2) "If yes: how does the action is applied to the url?"
According to the Sencha source code you need to define the actionMethods like so:
myApp.stores.Things = new Ext.data.Store({
model: "Things", proxy: {
type: 'ajax',
actionMethods: {
create: 'POST',
read: 'GET',
update: 'PUT',
destroy: 'DELETE'
},
url: 'jsontest.json',
reader: {
type: 'json',
root: 'things'
}
},
autoLoad: true
});
If you delete, create or edit a record you must call:
store.sync();
There is also a "autoSave" property but it only syncs on edits, not removes.
This will send over the things that have changed or been deleted as part of the request payload, it is your responsibility to parse the json and handle it.
Hering,
I was reading the documentation here, I found this example in the Model class:
Ext.regModel('User', {
fields: ['id', 'name', 'email'],
proxy: {
type: 'rest',
url : '/users'
}
});
But above you don't show your Model for app.models.Entry, have you tried that?