Displaying categories/subcategories in sencha - extjs

I have recently develop a sencha app about displaying categories/sub categories. It displayed the main categories, but does not display the sub categories on clicking any category.
My store is--
Ext.define('listdemo.store.Sections', {
extend : 'Ext.data.Store',
config : {
autoLoad: true,
model: 'listdemo.model.Sections',
proxy:{
type : 'ajax',
url:'http://localhost/catt.php',
reader:{
type:'json',
rootProperty:'categories'
}
}
}
});
Model code is------
Ext.define('listdemo.model.Sections', {
extend: 'Ext.data.Model',
config: {
fields: ['categories_id', 'categories_name','subcategories'],
}
});
And the view is----
Ext.define('listdemo.view.Main',{
extend: 'Ext.NestedList',
xtype:'main',
requires: [
'Ext.TitleBar',
'Ext.dataview.List',
'Ext.data.Store',
'Ext.dataview.NestedList'
],
config:{
title: 'Categories',
//store:'Sections',
items:[
{
xtype:'list',
itemTpl:'{categories_name}',
title:'Categories',
store:'Sections',
}
]
}
});
My php file returns----
{"categories":[{"categories_id":"1","categories_name":"Hardware","subcategories":[{"categories_id":"4","categories_name":"Graphics
Cards"},{"categories_id":"5","categories_name":"Printers"},{"categories_id":"6","categories_name":"Monitors"},{"categories_id":"7","categories_name":"Speakers"},{"categories_id":"8","categories_name":"Keyboards"},{"categories_id":"9","categories_name":"Mice"},{"categories_id":"16","categories_name":"Memory"},{"categories_id":"17","categories_name":"CDROM
Drives"}]},{"categories_id":"2","categories_name":"Software","subcategories":[{"categories_id":"18","categories_name":"Simulation"},{"categories_id":"19","categories_name":"Action"},{"categories_id":"20","categories_name":"Strategy"}]},{"categories_id":"3","categories_name":"DVD
Movies","subcategories":[{"categories_id":"10","categories_name":"Action"},{"categories_id":"11","categories_name":"Science
Fiction"},{"categories_id":"12","categories_name":"Comedy"},{"categories_id":"13","categories_name":"Cartoons"},{"categories_id":"14","categories_name":"Thriller"},{"categories_id":"15","categories_name":"Drama"}]}]}
What will I do to display the sub categories under main categories.

You need to update your model definition to include field types, and register a custom data type to use for subcategories.
Start by including this before the models load:
Ext.data.Types.ARRAY = {
type: 'Array'
};
Next update your model to look like this:
Ext.define('listdemo.model.Sections', {
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'categories_id',
type: 'int'
},{
name: 'categories_name',
type: 'string'
},{
name: 'subcategories'
type: Ext.data.Types.ARRAY
}]
}
});
Now once your store loads, check the records manually via the web console to ensure the array of subcategories is saved. You will need to add a listener for itemtap on the list, and then grab the subcategories and either:
-Reload the original store manually with the subcategories array. This should refresh the list, but you will lose the original store and there won't be any card animation.
-Set up a second list/store that will be reloaded manually with the subcategories, which will allow for the change card animation and maintain the original store for back navigation.

give your store the Store Id
2.pass the parameter categories_name and select the subcategory whose parent directory is categories_name
success: function (response)
{
searchresponse2 = Ext.JSON.decode(response.responseText);// getting response from server
//searchresponse2 is array storing 1st result in array index[0]
searchresponse2=searchresponse2[0];
var categoriesid=searchresponse2.categories;//getting 1st
values"categories_id":"1","categories_name":"Hardware"
var categoriesname=searchresponse2.categories_name;
del_categoriesid=[];//declaring array
del_categoriesname=[];
for(var i= 0;i<searchresponse2.length;i++)
{
del_categoriesid[i]=searchresponse2[i].categories;
del_categoriesname[i]=searchresponse2[i].categories_name;
}// looping through all values
for(var j= 0;j < searchresponse2.length;j++)
{
Ext.getStore('storeid').add({categories:del_categoriesid[j], categories_name:del_categoriesname[j]});
}// adding the values of the result in store

Related

extjs treestore with proxy type of rest appending -1 to model name

Having a peculiar problem with TreeStore where the rest type treestore adds -1 to name of model which breaks my backend routes.
TreeStore is defined as
Ext.define('Gateway.store.Company', {
extend: 'Ext.data.TreeStore',
model: 'Gateway.model.Company',
proxy: {
type: 'rest',
url: 'http://gateway-email-mock/',
reader: {
type: 'json'
}
}
});
where company model is defined as
Ext.define('Gateway.model.Company', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int' },
{name: 'name', type: 'string' }
]
});
The view interested in the store is
Ext.define('Gateway.view.company.Company', {
extend: 'Ext.tree.Panel',
alias: 'widget.company-list',
store: 'Gateway.store.Company',
rootVisible: false
});
When loading the widget the store creates URL
http://gateway-email-mock/Gateway.model.Company-1
How does -1 get there after the model name? I do not suppose this is intentional?
Thank you for any tips.
Rixo is correct, that is the tree store trying to load its root node. The default id generator generates its ID in the following way
idgen: {
isGenerator: true,
type: 'default',
generate: function () {
return null;
},
getRecId: function (rec) {
return rec.modelName + '-' + rec.internalId;
}
}
Which means your root record is rec.modelName + '-' + rec.internalId, which is exactly the request that is being made: http://gateway-email-mock/Gateway.model.Company-1
The solution is to make sure you create a root node with an ID, so that the tree's store will make a request for the correct ID , right it's generating the root node for you and giving it an automatic ID. See http://docs-origin.sencha.com/extjs/4.2.2/source/TreeStore.html#Ext-data-TreeStore-method-load and http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.data.TreeStore-cfg-root

Extjs4: How to share data between multiple stores or models?

I'm new to Ext and I'm struggling to figure out Models Stores and Proxies.
The server returns one large JSON object.
For example.
{
"responseHeader":{
"status":0,
"QTime":12,
"params":{
"facet":"true",
"facet.limit":"40"
}
},
"response":{
"numFound":3806,
"start":0,
"docs":[
{
//Lots of fields
"id":"1234",
...
//Some array properties
"testfield":[
"",
""
],
...
}
]
},
"facet_counts":{
"facet_queries":{
"email":3806
},
"facet_fields":{
"emailaddress":{
},
"subject":{
"candles":136,
"filter":130
},
"fromemail":{
},
//...
},
"facet_dates":{ },
"facet_ranges":{}
},
"highlighting":{
"some doc id":{
"emailtext":[ " Tel.: blah blah <em>blah</em>" ],
"combined":[ "<em>Email</em> To: blah blah blah" ]
}
}
}
I don't want to load this data more than once, I want to grab data from this object, for example the docs object, and put it into a grid. Then pull out another part to put into a selectbox.
How do I load this data once, yet create models and stores to give to grids and selectboxes, from it?
From what I read the proxy holds the servers response? So I tried creating a proxy out side of a store. Thinking I could use the same proxy with more than one store.
var myProxy1 = Ext.create('Ext.data.proxy.Proxy', {
type: 'ajax',
url : '../test',
reader: {
type: 'json',
root: 'responseHeader'
}
});
But when I pass myProxy1 to a store
Ext.define('Test', {
extend: 'Ext.data.Model',
fields: [
{name: 'status', type: 'int'},
{name: 'QTime', type: 'int'},
{name: 'param', type: 'auto'}
]
});
var myStore = Ext.create('Ext.data.Store', {
model: 'Test',
proxy: myProxy1,
autoLoad: true,
listeners:{
load: function( ths, records, successful, operation, eOpts ){
debugger;
}
}
});
It doesn't work. The load event is never fired. No data is loaded. I can see that the proxy made the request, I see the response from the server, but it doesn't load.
If I put the proxy inline it loads.
var myStore = Ext.create('Ext.data.Store', {
model: 'Test',
proxy:{
type: 'ajax',
url : '../test',
reader: {
type: 'json',
root: 'responseHeader'
}
},
autoLoad: true,
listeners:{
load:function( ths, records, successful, operation, eOpts ){
debugger;
}
}
});
I was thinking I could have one proxy, attach it to multiple stores, and just change the reader on it before I load the store.
You are pretty much there, and although I'm pretty sure you are understanding it all, for the benefit of others allow me to give an extended answer and a slightly modified solution to your problem.
Definitions:
The Model - primarily defines the fields a record has.
A Store - holds a collection of records.
A Proxy - facilitates server communication through a chosen method (Ajax, Direct, etc.) and maps CRUD (Create/Read/Update/Destroy) operations when such result from a change in the associated store or model.
A Reader - Tells a proxy how to interpret the data the server returns.
A Grid or Combobox - can display store records.
You scenario is not an uncommon one - while by default ExtJS loads each store separately, it is likely an application would prefer various stores to be loaded at once through a single read call; for example, when rendering one store-dependent component is dependent on another store.
Your code is not far off from achieving this, but here is how I do it. In effect, when a 'master' (Tasks) store loads, the server response also carries the data of a 'slave' (Tags) store, which is then manually loaded to that 'slave' store.
The 'slave' store (notice autoload: false and no read operation):
Ext.define('DL.store.Tags', {
extend: 'Ext.data.Store',
model: 'DL.model.Tag',
// Notice the tags are actually returned when the tasks are loaded and loaded into this store by the TasksStore.
autoLoad: false,
autoSync: true,
proxy: {
type: 'direct',
api: {
create: Tags.Create,
update: Tags.Update,
destroy: Tags.Destroy,
},
reader: {
type: 'json',
root: 'tags'
}
},
});
Then the 'master' store:
Ext.define('DL.store.Tasks', {
extend: 'Ext.data.TreeStore',
model: 'DL.model.Task',
autoLoad: true,
autoSync: true,
root: {
text: 'Root',
id: null,
expanded: true
},
proxy: {
type: 'direct',
api: {
create: Tasks.Create,
read: Tasks.Read,
update: Tasks.Update,
destroy: Tasks.Destroy,
},
},
onProxyLoad: function( aOperation )
{
// A read request for tasks will also return the user tags.
// So feed these tags into their store.
var iResult = aOperation.response.result,
iTagsStore = Ext.StoreManager.lookup( 'Tags' );
if ( Ext.isDefined( iResult.tags ) )
iTagsStore.loadRawData( iResult );
// We need this line for "Tasks" store to load its own data
this.callParent(arguments);
}
});
Basically all it does is it takes part of the server response and loads it manually to the 'slave' store.
The PHP server side code (for tasks read operation) involves:
return array(
'success' => true,
'children' => $iNodes,
'tags' => $iTags
);
Where children is the reader's root of the 'master' store, and tags is additional data that is then loaded into the 'slave' store.
I hope you can work how how to apply these concepts to your code.

Populating the value of a Label

I am using the MVC architecture (i have gone through the docs on MVC, but i am still lost here) and i need to know how to populate the records on to my Label. I know that i have to get this done by Stores.
I have loaded the values from the store, but unable to display it on my Panel for some reason. here's my code;
Most of the examples/books demonstrates how to display in a grid, but not a label (I know it has to be the same logic, but i am lost). And it shows how to write to a DB/JSON file and not display the values.
I need to display the COUNTRYNAME in the Label text. This is an example code that i am doing to understand this, can some one help me ?
Ext.define ('ProjectDisplayExample.model.Country',{
extend: 'Ext.data.Model',
//
fields:['countryid','countryname']
//
});
STORE
Ext.define('ProjectDisplayExample.store.Country',{
extend:'Ext.data.Store',
model:'ProjectDisplayExample.model.Country',
remoteGroup:true,
proxy: {
actionMethods : {
read : 'POST',
},
type: 'ajax',
url : '/server/country.php'
}
});
VIEW
Ext.define('ProjectDisplayExample.view.CountryWindow', {
extend: 'Ext.window.Window',
alias: 'widget.countrywindow',
...........
initComponent: function() {
var st = Ext.getStore('Country');
st.load();
this.items = [
{
items: [
{
xtype: 'panel',
region: 'north',
items: [{
xtype: 'label',
// NEED TO DISPLAY COUNTRT NAME FROM THE STORE HERE
}]
}]
}
UPDATE
var store = ... // Your store
store.on('load', function() {
// here store is loaded and you can do anything you want with it
console.log('store is loaded. number of records = ', store.getCount());
}, this, { single: true });
store.load; // I ADDED THIS LINE.................... <---------
UPDATE 2
this.items = [
{
items: [
{
xtype: 'panel',
region: 'north',
items: [{
xtype: 'label',
name : f
}]
}]
I will not post a code sample to exactly solve your question, but I will give you couple points:
Store contains array or records. So you can't just say give me country name from the store. You need first to get a record, for example: var r = store.getAt(0), and only after that you can get countyname field var f = r.get('countryname').
Load() method is asynchronous, so you can just execute it somewhere in the code and assume that for the very next line your store is ready. You need to subscribe to the load event, something like:
var store = ... // Your store
store.on('load', function() {
// here store is loaded and you can do anything you want with it
console.log('store is loaded. number of records = ', store.getCount());
}, this, { single: true });
store.load();
Labels as in xtype: label are actually very rarely used in ExtJs. What exactly are you trying to display in that panel? But anyhow... after you get data out of the store you can use something like update() or setValue() or any other method to update component.
Hope this helps...

Dynamic json chart

I'm trying to use Sencha Touch Charts with a JSONStore to dynamically display a chart from information provided by JSON, series and data. This was possible with ExtJS 3 with the metaData property.
How can I accomplish the same with Sencha Touch Charts?
// Am using ruby for the webservice calls.
// First u have to create model and store for that
// model
Ext.regModel('samplemodel', {
idProperty: 'name',
fields: [ { name: 'name', type: 'string' },
{ name: 'data', type: 'int' }
]
});
// store
Ext.regStore('SampleStore', {
model: 'samplemodel',
storeId: "sampleStoreID",
sorters: [ {
property: 'name'
}]
});
// and create a variable for the store
var sampleStore = Ext.getStore("SampleStore");
// call the webservice and store it in array,
// bind the response to the store,
// use the store variable in the chart.
http://www.sencha.com/forum/showthread.php?161912-Dynamic-json-chart

Sencha touch list group

I have a list:
{
xtype: 'list',
itemTpl: '{name}',
sorters: 'name',
getGroupString: function(record)
{
return record.get('name')
},
indexBar:true,
grouped: true,
store: {
fields: ['name', 'url'],
data: centres
},
itemConfig: {
tpl: '{url}'
},
listeners: {
itemtap:function(data,index){
var record = data.getStore().getAt(index);
redirect_url = record.raw.url
// the record that has been clicked.
window.location = redirect_url
}
}
}
I want to group the list by name. But results are not being grouped.
the sorters (takes an array of Strings), getGroupString are part of the store. The store also needs a model to back it.
I'm not sure what you're trying to do with both itemTpl and itemConfig displaying two different things, if you want to show the name property in the list then you just need the itemTpl.
See the KitchenSink List example:
http://docs.sencha.com/touch/2-0/#!/example/kitchensink/index.html
User Interface --> List and hit the Source button on the upper right hand corner.

Resources