I am very new to ExtJs and I have the following code for a treeView,,which has a default root in the beginning and then an Ajax call to a servlet .But i don't understand the 'root' field with value 'data' .Is data an alias or xType .Here is the code:
Ext.define('Eits.view.OrgTreeView', {
extend : 'Ext.tree.TreePanel',
requires: ['Eits.model.OrgTreeModel'],
width : '100%',
region : 'center',
border : true,
store : {
xtype : 'tree',
fields : Eits.model.OrgTreeModel.FIELDS,
//model: 'Eits.model.OrgTreeModel',
autoLoad: false,
root: {
id: 'rootNode',
objectId : 'rootNode',
leaf: false,
expanded: false,
text : 'MTS',
iconCls : 'mts-Tree-Node',
},
proxy: {
type: 'ajax',
url: 'orgTree/getNavigationTree.action',
actionMethods: 'POST',
reader: {
type: 'json',
root: 'data'
}
}
}
root property is:
The name of the property which contains the data items corresponding
to the Model(s) for which this Reader is configured. For JSON reader
it's a property name (or a dot-separated list of property names if the
root is nested). For XML reader it's a CSS selector. For Array reader
the root is not applicable since the data is assumed to be a
single-level array of arrays.
By default the natural root of the data will be used: the root JSON
array, the root XML element, or the array.
The data packet value for this property should be an empty array to
clear the data or show no data.
(Extjs's documentation is a great resource when using the framework)
Related
I'm an ExtJS (I'm using version 5.1) newbie and I'm trying to split a monolithic single file application in different files. I've moved a store outside in a separate file. This is the store in the separate file:
Ext.define("MT.store.MicroProfilerStore", {
extend: "Ext.data.JsonStore",
singleton : true,
model : 'MT.model.MicroProfilerModel',
storeId: "micro_profiler_store",
autoLoad: false,
proxy: {
type: 'ajax',
url: './backend/profiler.php',
reader: {
type: 'json',
rootProperty: 'answers'
}
}
});
If I use this file the ajax request is correct and I can see the reply but it looks like the store is ignoring the rootProperty and instead of having the array of answers in the store.getData() I have a single item array with the first value that is the entire response converted to javascript like:
[{success: 'true', answers: [{}, {}]}]
But If I create the store directly without subclassing using Ext.create("Ext.data.JsonStore", {...}) it's working!
The hack that I've found after a day of trying that allows me to keep a separate file for the store is this:
Ext.define("MT.store.MicroProfilerStore", function(){
Ext.require(['MT.model.MicroProfilerModel'], function(){
Ext.create("Ext.data.JsonStore", {
singleton : true,
model : 'MT.model.MicroProfilerModel',
storeId: "micro_profiler_store",
autoLoad: false,
proxy: {
type: 'ajax',
url: './backend/profiler.php',
reader: {
type: 'json',
rootProperty: 'answers'
}
}
});
});
return {};
});
Then I can get the store using StoreManger.lookup(). Ok it's working fine but the question is why ?
PS
I've already tried preloading the model before the store, explicity requiring the model and the store in many place It doesn't looks like a precedence error
Thanks for your help
We have many stores which could be made singleton, but it seems that singleton:true isn't part of ExtJS best practices.
If we need a "singleton store", which is like 90% of the time, we still make a normal store, but add that store to the stores array in Application.js, so that the instance is created before Application launch. What makes the store a singleton is a storeId, by which it is referenced from everywhere. All our singleton stores are defined using a special constructor/callParent construction, because we didn't get reader rootProperty to work otherwise:
Ext.define('MyApp.store.Directories',{
extend: 'Ext.data.Store',
storeId: 'DirectoryStore',
constructor: function() {
var me = this;
this.callParent([{
proxy: {
type: 'ajax',
headers:{'Accept':'application/json'},
noCache: true,
pageParam: false,
startParam: false,
limitParam: false,
extraParams: {
q: 'directory'
},
url: '../api/AddressBook',
reader: {
type: 'json',
rootProperty: 'data'
}
},
autoLoad: true
}]);
}
});
The special constructor/callParent part makes the difference here. We don't exactly know WHY it works, but it works - we copied that approach from Sencha Architect-generated code. If we now need that store's content anywhere, we do as follows:
xtype:'combo',
name:'Directory',
store:'DirectoryStore' // <- reference by storeId!
The storeId reference fails if we don't add the store to the stores array in Application.js, where we should keep a list of all "singleton" stores:
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
name: 'MyApp',
views: [
/* Allgemein */
...
],
controllers: [
'Configuration',
...
],
stores: [
'Directories',
...
]
I want to build the tree grid by parsing XML file.
I saw extJS XML TREE example but it require to have specific tags in XML file like id (to describe parent - child relationship), text (to print the tree node Name) , and leaf (to specify leaf and non leaf element) tags.
So, I have to manipulate my xml file to add these tags. But, is there any way i can achieve same result without adding extra tags?
Your going to want your own custom reader. You can use a custom reader to intercept your xml response and modify it before it goes into your store. For example, loading the following xml file will result in a grid where the first "foo" value is 11 :
Ext.define('MyReader', {
extend : 'Ext.data.reader.Xml',
alias : 'reader.myreader',
getResponseData: function(response) {
// Here is the xmlDocument you are going to change
var xmlDoc = response.responseXML;
// I change the first foo value to 11.
var fooValues=xmlDoc.getElementsByTagName('foo');
fooValues[0].innerHTML=11;
return this.callParent([response]);
}
});
Ext.define('Fiddle.view.Foo', {
extend : 'Ext.grid.Panel',
xtype : 'fiddle-foo',
store: {
autoLoad: true,
fields: ['foo'],
proxy: {
type: 'ajax',
url: 'data1.xml',
reader: {
type : 'myreader', // instead of xml
root : 'root',
record: 'fooRecord'
}
}
},
columns : [
{
text : 'Foo',
dataIndex : 'foo',
flex : 1
}
]
});
Ext.application({
name : 'Fiddle',
launch : function() {
new Fiddle.view.Foo({
renderTo : document.body,
width : 400,
height : 400,
title : 'Test'
});
}
});
You can check this out on sencha fiddle with this sample xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<fooRecord>
<foo>1</foo>
</fooRecord>
<fooRecord>
<foo>2</foo>
</fooRecord>
</root>
I understand you probably can't switch from XML to JSON since your not touching the server at all, but JSON is much simpler to parse if you are able to. You can find similar steps for that here: https://www.sencha.com/forum/showthread.php?261182-How-to-implement-custom-JSON-reader
I have a jqGrid working OK using the local datatype, but I now want the values to be loaded via json but having trouble changing it.
This is my jqGrid code
jQuery("#grid").jqGrid({
datatype: "json",
url: "/controller/getItems?id=2",
width: 1405,
colNames: ['id', 'surname'],
colModel: [
{ name: 'id', index: 'id', editable: false, hidden: false, hidedlg: true },
{ name: 'surname', index: 'surname', editable: true }
],
onSelectRow: function (id, status, e) {
...
},
editurl: url,
...
So the method to get the JSON is sucessfully fired.
[HttpGet]
public ActionResult getItems(string id)
{
List<model> items = method.getItems(id);
string jsonText = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(items);
return Json(jsonText, JsonRequestBehavior.AllowGet);
}
The column names in the JSON do match the colModel names
Example of the json being returned - what the object jsonText above contains
[{"id":434,"surname":"Woods"},
{"id":435,"surname":"Adams"}]
Is there anything I have done wrong or am missing?
Thanks
I suppose that the error in in using of System.Web.Script.Serialization.JavaScriptSerializer().Serialize. You need just return Json(items, JsonRequestBehavior.AllowGet);. Additionally you can remove the column id from the colModel. The id value will be still read and assigned as the value of id attribute of the rows (id of <tr> elements of the grid) known as rowid. You should add loadonce: true option to the grid because you don't implemented paging of data on the server side and to add gridview: true (if you not already use it) to have better performance and autoencode: true to interpret input data as texts instead of HTML fragments.
UPDATED: In case of usage old version of jqGrid one have to include jsonReader parameter which corresponds the format of input data:
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; }
}
One should still use loadonce: true option additionally.
In Ext JS I have data store with JSON reader.
I generate models from classes on server side, with same hierarchy - eg. on server I have CustomerDto class which extends BaseDto class;
on client side I also have CustomerDto which extends BaseDto, and BaseDto extends Ext.data.Model.
Let's say I define data store with model SuperCustomerDto (which extends CustomerDto) and send mixed list of SuperCustomerDto and CustomerDto from server, they are always deserialized as CustomerDto.
Is there a way to configure data store in Ext JS, so it can distinguish actual model type? So in my case list should contain few SuperCustomerDto and few CustomerDto.
In Ext JS 5 you can set typeProperty which will indicate the type of the model to be created.
Example store:
var store = Ext.create('Ext.data.Store', {
model: 'CustomerDto',
proxy: {
type: 'memory',
reader: {
type: 'json',
typeProperty: 'cls',
rootProperty: 'data'
}
}
});
Example data:
[
{ cls: 'CustomerDto', id: 1, a: 'a' },
{ cls: 'SuperCustomerDto', id: 2, a: 'a', b: 'b' }
]
If typeProperty is set to cls, reader will conver first array element to CustomerDto, and second to SuperCustomerDto.
In Ext JS prior to 5 AFAIK there is no build-in support for that. To mimic this behaviour you should override Ext.data.reader.Reader.extractData method.
Working sample: http://jsfiddle.net/b2LS5/1/
i'm trying to set a pagingtoolbar on my livesearchgridpanel.i'm getting the data over a Httpproxy ,so here is my store :
tempStore = new Ext.data.Store
({
groupField : default_groupby_s,
model : 'reportWorkspace',
allowFunctions : true,
autoSync : false,
pageSize : 20,
autoLoad : true,
remoteSort : false,
proxy : new Ext.data.HttpProxy
({
url : url_s,
actionMethods :
{
read : 'POST'
},
reader :
{
type : 'json',
root : 'workspace_report',
successProperty : 'success'
}
})
});
return tempStore ;
}
and here is my pagingtoolbar ,it will be included in my LivesearchgridPanel:
{
xtype: 'pagingtoolbar',
store: tempStore ,
dock: 'bottom',
pageSize:20,
displayInfo: true
}
the problem,it's that the pagingtoolbar is displaying pages correctly,but in the case of my grid,it displays ALL the data at the same time (in every page) . is it possible to do it without setting any starting point or limit in the autoload param ??
i just want to download all my data and then display it Correctly with pages
Any suggestion Please ?
I see several incosistencies:
LiveGrid was not built for paging at all but as an alternative to it.
ExtJS 4.1x no longer uses HTTP Proxy class but instead uses type: 'ajax' proxy config.
If you are going to page your data, you need to remote sort it, otherwise it won't make sense.
You have to make sure your grid panel and your pagingtoolbar refer to the same store instance. A common config for that in a grid panel is:
.
this.dockedItems = [
{
xtype:'pagingtoolbar',
store:this.store, // same store GridPanel is using
dock:'bottom',
displayInfo:true
}
];