I have read the Sencha tutorials, API, and forums for awhile but am hitting a brick wall. I have a mySQL/PHP backend that is storing a web application's data. I have the following Sench/ExtJS construct:
App.stores.user = new Ext.data.Store({
model: 'User',
proxy: new Ext.data.AjaxProxy({
url: 'app/stores/scripts/connect.php',
extraParams: {
method:'user',
user_id: 3
},
reader: {
type:'json',
root:'root'
}
}),
autoLoad:true
});
Data is loaded into the store fine, but I have a form that directly updates a User instance.
App.controllers.account = new Ext.Controller({
save: function (options) {
options.user.set(options.data);
options.user.save(); // Generates error: Uncaught Error: You are using a ServerProxy but have not supplied it with a url.
}
});
How can I successfully implement/hook the functions to write the dirty records back to the server? How is the request prepared and passed?
Thank you.
Uptil Ext Js 3.3.1 the store needs to be configured with a writer when performing CRUD operations. It isn't needed for read only. That's why your store is loaded but you're getting an error during write operations. In your case you'll have to specify a JsonWriter. Also, if you're not using the store in a restful manner, then you'll also need to specify a HttpProxy object to tell the store at which url to publish the create/update/delete on the store.
Check the docs for Ext 4. I should be something similar here too.
Related
I have 2 stores with different models but same direct proxy configuration. When i load these 2 stores (i call store.load() for both stores at the same time) ext is sending only one request (containing both loads) and the second store is not populated with data. I tried setting batchActions to false with no success. I am using ext direct spring on server side.
Proxy configuration:
proxy: {
type: 'direct',
batchActions:false,
directFn:doctorDirectController.getAll,
reader:{
type:'json',
root:'records'
}
}
When i set timeout for 1 sec everything works fine:
this.doctorStore1.load();
var me = this;
setTimeout(function() {
me.doctorStore2.load();
}, 1000);
So the 2 questions:
How to force directproxy not to batch getAll requests
Why second store is not being populated with data? The request and response contains tids that match up.
It turned out to be problem with Spring. To handle cycling references between entities (which caused problems during jackson serialization) i used following annotation
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#doctorId")
When simultaneous 2 store loads occured they were serialized in one batch and send back in one response. The above annotation was removing all the duplicates during json serialization causing second store not to be populated with data.
I have a grid with remote data (php/mysql/json) and use a form to insert records or to edit this data.
I use the api configuration of the proxy/store. I use MVC architecture.
So, all very simple (in pseudo code):
get selected model form grid or create model
frm.loadRecord()
frm.updateRecord()
frm.getRecord().save()
and all works fine, but I noticed in the browser console that after the POST (works fine, calls either the url configured with create or the url configured with update), the store calls (GET) the url configured with retrieve twice. These calls are identical.
So functionally all works fine and I could ignore it, but now I've noticed I want it fixed.
Can anyone help me where to look? Thanks in advance.
Details:
It's all really basic:
In the controller of the gridpanel:
updateRow: function (gridpanel) {
var sm = gridpanel.getSelectionModel();
var record = sm.getLastSelected();
this.showForm(record);
}
and
showForm: function (record) {
...
formpanel.show();
var frm = formpanel.getForm();
frm.loadRecord(record);
}
In the controller of the formpanel:
submit: function(frm) {
frm.updateRecord();
frm.getRecord().save();
}
When I remove the save action the GET requests aren't called, so this seems to trigger them.
In the store:
api: {
create: '../php/api/customers.php?request=create',
read: '../php/api/customers.php?request=retrieve&scope=summary',
update: '../php/api/customers.php?request=update',
destroy: '../php/api/customers.php?request=delete'
}
The screenshot:
OK, I'm stuck on what should be a basic task in ExtJs. I'm writing a simple login script that sends a user name and password combination to a RESTful web service and receives a GUID if the credentials are correct.
My question is, do I use a Model Proxy or a Store Proxy?
To my understanding, Models represent a single record, whereas Stores are for handling sets of data containing more than one record. If this is correct then it would seem that a Model proxy is the way to go.
Following Sencha's documentation at http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Model the code would look something like this:
Ext.define('AuthenticationModel', {
extend: 'Ext.data.Model',
fields: ['username', 'password'],
proxy: {
type: 'rest',
url : '/authentication'
}
});
//get a reference to the authentication model class
var AuthenticationModel = Ext.ModelManager.getModel('AuthenticationModel');
So far everything is OK, until the next step:
//Use the configured RestProxy to make a GET request
AuthenticationModel.load('???', {
success: function(session) {
console.log('Login successful');
}
});
The load() method for the Model class is a static call expecting a single unique identifier. Logins typically depend upon two factors, username and password.
So it appears Store proxies are the only way to validate someone's username and password credential combination in ExtJS. Can someone verify and explain? Any help to understand this would be greatly appreciated.
You just need to know the following:
The store will use it's own proxy if you configured one for this
instance and if not he takes the proxy from the model.
So you can easily go with two proxy configurations to enable the multi-CRUD operations on the store and the single-CRUD operations on the Models. Note the the static load method of the Model expects the model id because it is supposed to load a model by just one Id (yes, composite keys are not supported). You will also have to fetch the model instance in the callback (As you did).
Back to your Username/password problem
You may apply your session Model with a custom 'loadSession' method
loadSession: function(username,password, config) {
config = Ext.apply({}, config);
config = Ext.applyIf(config, {
action: 'read',
username: username,
password: password
});
var operation = new Ext.data.Operation(config),
scope = config.scope || this,
callback;
callback = function(operation) {
var record = null,
success = operation.wasSuccessful();
if (success) {
record = operation.getRecords()[0];
// If the server didn't set the id, do it here
if (!record.hasId()) {
record.setId(username); // take care to apply the write ID here!!!
}
Ext.callback(config.success, scope, [record, operation]);
} else {
Ext.callback(config.failure, scope, [record, operation]);
}
Ext.callback(config.callback, scope, [record, operation, success]);
};
this.getProxy().read(operation, callback, this);
}
Now call this instead of load.
I found it in the documentation of sencha App Architecture Part 2
Use proxies for models:
It is generally good practice to do this as it allows you to load and
save instances of this model without needing a store. Also, when
multiple stores use this same model, you don’t have to redefine your
proxy on each one of them.
Use proxies for stores:
In Ext JS 4, multiple stores can use the same data model, even if the
stores will load their data from different sources. In our example,
the Station model will be used by the SearchResults and the Stations
store, both loading the data from a different location. One returns
search results, the other returns the user’s favorite stations. To
achieve this, one of our stores will need to override the proxy
defined on the model.
I am adapting a tutorial to change from localstorage to use a java servlet but i am having some problems. I am trying to update the changes a user makes by calling sync() but i am getting these errors.
[WARN][Ext.data.Operation#process] Unable to match the record that came back from the server.
I tried seeing if the updated values where being send to the servlet
String name = request.getParameter("name");
is null. How do I send the updated values back the server and read them? I tried looking for a sencha touch + servlets tutorial but can't find anything
this is my sync code
var showsStore = Ext.getStore("Shows");
if (null == showsStore.findRecord('name', currentShow.data.name)) {
showsStore.add(currentShow);
}
showsStore.sync();
The expected return for a store sync is an array of JSON records, or nothing.
Add this to your data store
writer: {
type: 'json',
rootProperty: 'data',
encode: true,
writeAllFields: true
},
I'm working on creating a model in backbone to interact with my postgres database. I'm using backbone.js for the client side and node.js/sequelize.js for the server side. The code given in the backbone tutorial says this:
var UserModel = Backbone.Model.extend({
urlRoot: '/user',
defaults: {
name: '',
email: ''
}
});
Here they are interacting with a users sql database using a RESTful url (I have no idea what that is). Does anyone have any ideas how I can refer to my postgres table? I am beyond confused and have no idea what's going on (this is all really new to me)
Thanks.
A RESTful URL is just a URL for a webservice that uses RESTful principles. Google can explain that better than I can here, but the basic idea is to integrate the various REST "verbs" (GET, POST, DELETE, etc.) in to the API. For instance, here's a set of RESTful verbs + urls for an imaginary user API:
GET /user - returns a list of users
POST /user - creates a new user
DELETE /user/5 - deletes the user with ID 5
PUT /user/5 - updates/edits the user with ID 5
Backbone works particularly well if your server-side is designed similarly, but it's not a requirement.
If your server-side API isn't RESTful, you just need to override certain methods on your Models and Collections (most likely destroy, fetch, save, url, parse, sync, and toJSON) to do whatever is appropriate for your server.
For instance, you might want to override the url method of your model to make it return your server's (unRESTful) URL:
url: function() {
return 'www.example.com/some/very/not/RESTful/' + this.id + '/URL/example';
}
Or, if your server returns your objects with an "envelope", for instance:
{
type: 'envelope',
payload: {
type: 'user',
name: 'Bob',
id: 5,
}
}
you can modify parse to strip it out:
parse: function(original) {
return original.payload;
}
As for "how do I refer to my postgres table", if you override the appropriate methods, then call the appropriate Backbone action methods (fetch/save/destroy) on your models and collections, Backbone will make AJAX requests to the URL you define in your url override. Your server can then use any language you want to interpret that request and perform the appropriate operation on your PostgreSQL database.