Dynamic json chart - extjs

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

Related

Trying to get a basic combo to work in ExtJS

I want to use a very simple combo box in ExtJS, but I was surprised to learn that it seems as though I have to complexify things by using a store.
I have a single array of data :
var states = [
{"name":"Alabama"},
{"name":"Alaska"}
]
I create my model 'State' linking to the 'name' field, and then I create my store linking to the model, and the array of data.
Ext.regModel('State', {
fields: [
{type: 'string', name: 'name'}
]
});
var store1 = Ext.create('Ext.data.Store', {
model: 'State',
data: states
});
Now I create my combo, as a field in my panel :
var f = Ext.create('Ext.form.Panel', {
items: [
{
fieldLabel: 'hi there',
xtype: 'combobox',
name: 'XXXX',
store:store1,
maxLength: 64,
allowBlank: false
}
]
})
Nothing tells me that I am doing anything wrong, but I get an 'Uncaught TypeError: Cannot read property 'indexOf' of undefined ' whenever I try and open the combo.
My fiddle is here :
http://jsfiddle.net/sr61tpmd/1/
Another aside to my question is, what is the simplest way I can present a combobox in ExtjS?
As long as you only want a combo box with same value as displayed, it is entirely possible to define the store as an array.
xtype:'combo',
store:['Alabama','Arkansas',...]
A real extjs store is necessary where your displayed text differs from the value. You can see a working example for this (also using the us states, actually) in the ext docs: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.form.field.ComboBox

Displaying categories/subcategories in sencha

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

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...

extjs Event to update a Grid

I need a grid built in extjs designer to add data to the grid on an event.
so I should have a function that when called with receivedMsg as Args, sends the array data to be added as a new record in the grid.
I do not want it to go out and refresh a json file, not very network friendly.
I have written the server backend myself, and implemented websockets to generate the receivedMsg event.
How can I do this?
Here is where the event should go:
/*
* File: app/view/MyGridPanel.js
* Date: Sat Jan 14 2012 14:58:07 GMT-0500 (Eastern Standard Time)
*
* This file was generated by Ext Designer version 1.2.2.
* http://www.sencha.com/products/designer/
*
* This file will be generated the first time you export.
*
* You should implement event handling and custom methods in this
* class.
*/
Ext.define('MyApp.view.MyGridPanel', {
extend: 'MyApp.view.ui.MyGridPanel',
initComponent: function() {
var me = this;
me.callParent(arguments);
}
});
[
["Ace Supplies", "Emma Knauer", "555-3529"],
["Best Goods", "Joseph Kahn", "555-8797"],
["First Choice", "Matthew Willbanks", "555-4954"],
["First Choice", "Matthew Willbanks", "555-4954"]
]
If I understand the question properly, the array that you want to add as a record would first have to be converted into an instance of the same Ext.data.Model that your grid is using. Then you could call your "grid.store.insert()" method. For example, if your grid is using a model called 'Employee' like this:
// Grid data model
Ext.define('Employee', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'int'},
{name: 'email', type: 'string'},
{name: 'start', type: 'date'},
{name: 'salary', type: 'int'},
{name: 'active', type: 'bool'}
]
});
You could create the model instance outside of the function with your data and just pass that as the function args, or if you can only get the data as an array (hopefully you can set the sequence), you can create the model instance inside the function itself, shown here:
// the function you wanted
addRecord: function(myRecordArray) {
// Create a model instance
var r = Ext.create('Employee', {
name: myRecordArray[0],
email: myRecordArray[1],
start: myRecordArray[2],
salary: myRecordArray[3],
active: myRecordArray[4]
});
// get the grid store and the number of records in it
var store = this.getStore();
var maxIndex = store.getCount();
// adds record to the end of the grid (args are: index, Ext.data.Model[])
store.insert(maxIndex, r)
}
You would probably have to tweak this depending on how your store is set-up but that should get it started.

Resources