Sencha Architect XML TreeStore fails to load/map XML - extjs

I'm trying to use XML TreeStore in Sencha Architect and it fails to load any data from the given XML. While I can access that store as an object, its getCount() returns 'undefined' and methods like getNodeById('foobar') result in 'cannot read property 'foobar' of undefined' which makes me think the mapping doesn't happen (store is initialised but failed to parse the data / instantiate models).
The same XML with the same model but accessed via a flat store in the same basic setup works fine (e.g. getCount() returns 2 as expected). Tree store with a JSON version of data again works fine as well.
The class for my problematic store by Sencha Architect is:
Ext.define('MyApp.store.DocumentStore', {
extend: 'Ext.data.TreeStore',
requires: [
'MyApp.model.Document'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: true,
storeId: 'TreeDocumentStore',
model: 'MyApp.model.Document',
proxy: {
type: 'ajax',
url: 'DocumentTemplates.xml',
reader: {
type: 'xml',
root: 'Templates',
record: 'Template'
}
}
}, cfg)]);
}
});
The source XML file store refers to is:
<?xml version="1.0" encoding="UTF-8"?>
<Templates>
<Template>
<Id>A253338C-CDFA-4182-9E1C-652EAAB713F8</Id>
<Title>Template 1</Title>
<Children />
</Template>
<Template>
<Id>26D5B83C-7E9E-49E2-B174-F9A6C7BA07A8</Id>
<Title>Template 2</Title>
<Children />
</Template>
</Templates>
In case I have misunderstood the purpose of 'root' property I tried different node names for global root and supposed child node roots setting 'root' property of the reader to all the possible values, but no luck.
I tried to remove empty from the nodes as well, same effect.
This is not about displaying items from the store in a view yet, I'm only trying to access the data in controller.
P.S. Dummy project with an XML file, tree store and controller accessing that store in onLaunch is here: http://sdrv.ms/RAsj26

Having spent some time with this issue my own answer to a similar question is probably relevant: https://stackoverflow.com/a/12886943/454266
Looks like tree structures for XML sources are not supported properly in the current version of framework, be it TreeStore or association mechanisms.

Related

How come store.add() method does not perform mapping?

I have a nested json data, namely:
{
name: 'alex',
tel: {
personal: '347xxxx',
work: '331xxxx'
}
}
Then the following model:
Ext.define("Employer", {
extend: 'Ext.data.Model',
idProperty: 'personalTel',
fields: [...
{name: 'personalTel', mapping: 'tel.personal'}
Finally the following store:
Ext.create('Ext.data.Store',{
model: 'Employer',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'root'
}
},
data: myInitialData //an array containing json objects
As long as the data is contained in myInitialData the personalTel field is correctly set.
However, adding a new record to the store does not trigger the mapping and so I find myself with strange personalTel property, that is automatic IDs extjs puts!
ExtJS allows you to load multiple models via nesting when using a reader. It does not allow those models to be created when instantiating the model directly, which is what adding the object to the store does.
The idea is that each model is treated separately with its own store. Want to add a customer with a telephone number? Create the telephone number first, put it in its store, then create the customer with a reference to the telephone number.
This approach is a bit clumsy, though, and only works with models that really are separate entities.
An alternative approach would be to use a custom type, or simply to use the 'auto' type (which treats the data as a blob that you can do what you want with). Both approaches have their drawbacks.

Returning string as json in extJs

I am working on extJs 3.2.x
I have a simple function which returns a string.
public Object getRevenueCurrency(....) {
return "USD";
}
I have Jackson mapper to map the response type to JSON.
<bean name="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="contentType">
<!-- <value>application/json</value> -->
<value>text/html</value>
</property>
</bean>
An attempt to retrieve the data goes like this:
currencyStore = new Ext.data.JsonStore({
id:'currencystore',
url: 'xxxxxxx?action=getcurrency',
root: 'string',
listeners: {load: function(store) {
rev_currency=store.?????;
}
}
});
currencyStore.on('exception',function( store, records, options ){
alert('Exception was called');
},this);
Fiddler shows a response from server as :
{"string": "USD"}
Although I get no server or js exception,the exception alert is called.
1.How do i extract the currency value ?
2.What is a way to extract a meaningful information on the exception in the exception handler above?
Concerning your second question:
2.What is a way to extract a meaningful information on the exception in the exception handler above?
According to the docs for the exception event the signature and parameters are:
exception( store, type, action, options, response, arg )
By inspecting the parameters (e.g. by console.log(...)) you should retrieve some useful information.
I notice you have not configured any fields on your store, so when the reader takes your json respsonse its trying to find a field named 'string' to bind to.
Take a look at the ExtJS3 docs for the JsonStore -> http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.JsonStore
The sample config shows you how the fields are defined, so your store should look like:
currencyStore = new Ext.data.JsonStore({
id:'currencystore',
url: 'xxxxxxx?action=getcurrency',
fields: ['string'],
listeners: {load: function(store, records, options) {
rev_currency=store.?????;
}
}
});
Note I have also changed the params to your load function handler, so the new record created from your json can be accessed using records[0]
You have configured the store by setting the root property which means the store's reader is expecting a root node in the json matching 'string'.
So the reader is actually expecting the below form of response.
{"string":[{"propertyname":"USD"}]}
Instead you could just take out the root property on your store config since all that's being returned is a flat object

Map JSON Object to Model/Store

I'm using Worklight framework to construct a mobile app for IOS, and is using Sencha Touch 2.3 to build the app.
Due to the environment, i cannot use proxy in Sencha Touch Store/Model objects to load data from the server, as i would need to use Worklight's adapter to retrieve the info. I have managed to do that using some boilerplate codes.
However, i wish that i could utilize the Sencha Model more, and as such, am thinking whether it is possible for me to load a JSON object into the Model object automatically, without specifying a proxy.
Currently i'm doing a lot of loop and setter call to load the data from the JSON object to a model, like below:
var profile = Ext.create('Profile', {
Id: rawProfile.Id,
Name: rawProfile.Name
Age: rawProfile.Age
.....
}
where rawProfile is the JSON object i loaded from the server.
Any way i can make this cleaner?
You could create a Model class which would contain the data contained in your rawProfile object.
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [{
name: 'Id',
name: 'Age',
...
}],
proxy: {
type: 'memory',
reader: 'json'
}
});
I've also set an in memory proxy which will read json objects.
You could then create a Store which would use the model you defined and the in memory proxy (meaning you wouldn't be using Ext's build in ajax messaging).
Ext.create('MyStore', {
model: 'MyModel',
autoLoad: false
});
Setting the autoLoad to be false, as you want to get the data from a different source.
Therefore, once you have your json object you can load it into the store by calling store.loadRawData(jsonObject).
In this case, the jsonObject would be the object containing all the json objects returned from the server, meaning that your code doesn't have to handle iterating through the records and you can leave it to the Sencha classes.
However you would need to figure out the writing data back to the server.
I'd recommend running through the Sencha Data Package tutorial as it gives a good intro to the data package
If all the fields map 1:1 with the json object, you can do this:
var profile = Ext.create('Profile', rawProfile);
Alternatively (or to avoid the convert functions for fields to be called), you can directly set the data property on the created model.
var profile = Ext.create('Profile');
profile.data = rawProfile;
Again, this requires a 1:1 on the fields and json object.

How to have several CRUD methods using a proxy with Sencha Touch 2 framework?

I've coded a small mobile application using Sencha Touch 2 framework. For the moment, I manage some articles from a database in localhost. I've written a database management using PHP CRUD methods contained here in ArticleService.php file. My 'read' fonction get back all the articles. But I want to have an other 'read' method to read for exemple a specific article according to its id or the last 5 articles, etc. But the store proxy (I think so) allows 1 methods for each main operation. So in my case, for 'read' operation I just have an only 'read' method.
Here's is my 'store' source code :
Ext.define("MyApp.store.ArticleStore", {
extend: "Ext.data.Store",
requires: ["MyApp.model.ArticleModel"],
config: {
model: "MyApp.model.ArticleModel",
proxy: {
type: "ajax",
api: {
create: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=create",
read: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=read",
update: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=update",
destroy: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=destroy"
},
extraParams: {
keyword: ""
},
reader: {
type: "json",
rootProperty: "articles",
totalProperty: "total"
}
},
autoLoad: true
}
});
Is there a possible way to have several methods for each main CRUD operation (for example 3 differents 'read' methods to manage my articles display) ? I'm really lost.
Thanks in advance for your help!
You don't need different methods for read. Once you load the store it will be in the memory and you will be able to find any record you want.
If you're store is too big to be loaded at once - take a look at remoteFilter property: http://docs.sencha.com/touch/2.1.1/#!/api/Ext.data.Store-cfg-remoteFilter This way filters you will set up (like id = 1 or parent_id = 2) will be passed to the server so it can return proper record set.

Ext-JS 4.1 - How to load static XML data into Ext.data.TreeStore

I was wondering if someone could point me in the direction of where I could find an example of a Ext.data.TreeStore being loaded from a static XML string (i.e. not from a file)? Or provide a short example?
I have seen plenty of examples where you can load it from a AJAX call to a server, but I have not been able to locate a single example where it is loaded with static XML JavaScript string that you could have embedded in your application file.
Would really appreciate the help.
Thanks.
You will need an XML store. Take a look at this:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.XmlStore
edit: The above might not work for trees. You can set the reader of your proxy on XML though:
var store = Ext.create('Ext.data.TreeStore', {
model: 'my.Model',
proxy: {
type: 'ajax',
url : 'path/to.xml',
reader: {
type: 'xml',
root: 'data'
}
},
root: {
expanded: true
}
});

Resources