-
31 May 2012 10:49 AM #11
I have the same issue, any simple solutions to access the hasMany elements to show
I have the same issue, any simple solutions to access the hasMany elements to show
What I need to do is display the following arrays in Grids, but at the moment really struggling to find any simple examples of this
I have a form which will show the basic information, then with this will be three seperate grids holding, comment information, tag information and Version information.
This is my model definition, when viewed under FireBug, I can see all the data I need,
How do I show these hasMany items in there own grids ?Code:Ext.define('DocDetails', { extend: 'Ext.data.Model', fields: [ { name: 'DocumentID', type: 'int' }, { name: 'Title', type: 'string' }, { name: 'Version', type: 'int' }, { name: 'Author', type: 'string' }, { name: 'LastAmended', type: 'date' }, { name: 'FileAmended', type: 'date' }, { name: 'UserID', type: 'string' }, { name: 'FileID', type: 'int' }, { name: 'Synopsis', type: 'string' }, { name: 'FileInfoID', type: 'int' }, { name: 'DocumentStatusID', type: 'int' }, { name: 'Icon', type: 'string' }, { name: 'Tags' }, { name: 'Comments' }, { name: 'Versions' }, { name: 'Success' }, { name: 'ErrMsg', type: 'string' }, ], associations: [ { type: 'hasMany', model: 'Tags', name: 'tags' }, { type: 'hasMany', model: 'Comments', name: 'comments' }, { type: 'hasMany', model: 'Versions', name: 'versions' } ] }); Ext.define('Tags', { extend: 'Ext.data.Model', fields: [ { name: 'DocumentID', type: 'int' }, { name: 'TagMasterID', type: 'int' }, { name: 'TagCategoryID', type: 'int' }, { name: 'TagCategoryName', type: 'string' }, { name: 'TagCategoryDescription', type: 'string' }, { name: 'TagDataTypeID', type: 'int' }, { name: 'TagTextVal', type: 'string' } ], belongsTo: { model: 'DocDetails', foreignKey: 'DocumentID' } }); Ext.define('Comments', { extend: 'Ext.data.Model', fields: [ { name: 'DocumentID', type: 'int' }, { name: 'UserID', type: 'string' }, { name: 'Comment', type: 'string' }, { name: 'Created', type: 'date' } ], belongsTo: { model: 'DocDetails', foreignKey: 'DocumentID' } }); Ext.define('Versions', { extend: 'Ext.data.Model', fields: [ { name: 'DocumentID', type: 'int' }, { name: 'Title', type: 'string' }, { name: 'Version', type: 'int' }, { name: 'Author', type: 'string' }, { name: 'LastAmended', type: 'date' } ], belongsTo: { model: 'DocDetails', foreignKey: 'DocumentID' } });
-
31 May 2012 10:53 AM #12
srarnold, did you want each child in the relationship to be nested in grids under the grid? Or flat out in a single row?
-
31 May 2012 11:08 AM #13
The top part of the form has static display, this information is not in a grid, but what I do need is the Comments to be in a grid, as they will be allowed to add new comments to this, also I need a grid for the Tags, this also will also need to allow additions and deletions also the facility to edit the items, attached the screen as it is at the moment:
fdetails.jpg
-
31 May 2012 11:16 AM #14
-
31 May 2012 11:30 AM #15
Another question about this solution. If I have father[i].daughter1 and have a property called name, how do I go about specifying that as a dataIndex on a column?
I tried dataIndex: daughter1.name but that doesn't work.
Note: That is a set the dataIndex to just daughter1, it comes in the grid as Object. So I know I have the object attached to the parent object.
EDIT:
I was able to get this to work using a template column.
There probably is a better way to do this.Code:text: 'daughter name', xtype: 'templatecolumn', tpl: '{' + daughter + '.name}'
I am still looking for an answer to my question at the bottom of the first page.
-
31 May 2012 2:19 PM #16
On the question from the first page, you don't actually need to use store.each(). The callback from the load() function receives an array of records as an argument so you can just do a normal loop through those model instances rather than using store.each.
As far as getting the dataIndex on the column to work right, I think you would need to avoid using a full daughter model instance as the value for the daughter field. Just concatenate whatever you want to display when you flatten it into a single value. Then you don't have to deal with the column template and can set each dataIndex to ("daughter" + i) or whatever you feel like serializing the field names to.
Code://Goals var flatGrid; var flatStore; var data = []; var maxDaughters = 0; this.fatherStore.load({ scope: this, callback: function(records, operation, success) { if (success === true) { //Loop records for (var i = 0, l = records.length; i < l; i++) { //Get daughters store var dStore = record[i].daughters(); //Update max daughters if (maxDaughters < dStore.count()) { maxDaughters = dStore.count(); } //Add all the father info to the data object for the flat store data[i] = record.getData(); //Loop through daughters and add to the flat data var x = 0; dStore.each(function (record) { //you could concatenate First + Last here data[i]['daughter' + x] = record.get('first') + record.get('last'); }, this); } flatStore = //Build new store with (maxDaughters - 1) ("daughter" + i) named fields flatGrid = //Build new grid with (maxDaughters - 1), ("daughter" + i) indexed columns, and use flatStore as the data store } else { Ext.Error.raise('Oh no!'); } } });
-
31 May 2012 2:34 PM #17
You have to build the flattened store inside the callback function for store.load(). Pretty much anything you do after the load call needs to be inside that function otherwise all the code will be executed out of order since load is an asynchronus xhr request. If it's getting too far nested that way, I would suggest doing everything after the store load in another named function and just referencing the function and scope in the callback.
Code:store.load(function(records) { parseRecords(records); buildFlatStore(); buildFlatGrid(); }, this) var parseRecords = function(records) {...} var buildFlatStore = function() {...} var parseRecords = function() {...}
-
1 Jun 2012 3:03 AM #18
Soted this out and in a very easy way
Soted this out and in a very easy way
1. Create a new Model just for the Array Element of the Parent Model.
2. Assign this empty model as the Store to the grid
3. This is my Store.load
Now I'm happy it is working the way I want it toCode:store.load({callback: function(rec, options, success) {if (success) {var dtComments = rec[0].data.Comments; commentStore.loadData(dtComments); grid.reconfigure(commentStore);}}});
-
1 Jun 2012 6:55 AM #19
Got it working using the method sdt6585 suggested
Unfortunately the sort for the flatten fields are not working, but I'll keep banging on it for a little and see if I come up with anything.Code:Ext.onReady(function() { // models Ext.define('Daughter', { extend: 'Ext.data.Model', belongsTo: 'Father', fields: [ 'age', 'name' ] }); Ext.define('Father', { extend: 'Ext.data.Model', fields: [ 'id', 'married', 'name', 'sons' ], hasMany: 'Daughter' }); // store Ext.create('Ext.data.Store', { storeId: 'fatherStore', autoLoad: true, model: 'Father', proxy: { type: 'ajax', url: 'data1.json', reader: { root: 'fathers' } }, listeners: { load: function(store, records, successful, eOpts) { if (!successful) { return; } var fathers = []; var maxDaughters = 0; Ext.Array.forEach(records, function(record) { var number = record.daughters().data.items.length; if (number > maxDaughters) { maxDaughters = number; } var father = record.data; for (var i=0; i < number; i++) { father['daughter' + i] = record.daughters().data.items[i].data; fathers.push(father); } }); buildGrid(fathers, maxDaughters); } } }); var buildGrid = function(fathers, maxDaughters) { var buildFields = function(maxDaughters) { var fields = [ 'id', 'married', 'name', 'sons' ]; for (var i = 0; i < maxDaughters; i++) { fields.push('daughter' + i); } return fields; }; Ext.create('Ext.data.Store', { storeId: 'flattenedStore', autoLoad: true, fields: buildFields(maxDaughters), data: { fathers: fathers }, proxy: { type: 'memory', reader: { type: 'json', root: 'fathers' } } }); // columns var buildColumns = function(maxDaughters) { var columns = [ { xtype: 'rownumberer' }, { text: 'name', dataIndex: 'name' }, { text: 'married', dataIndex: 'married' }, { text: 'sons', dataIndex: 'sons' } ]; for (var i = 0; i < maxDaughters; i++) { var d = 'daughter' + i; columns.push({ text: d, columns: [ { text: 'name', xtype: 'templatecolumn', tpl: '{' + d + '.name}' }, { text: 'age', xtype: 'templatecolumn', tpl: '{' + d + '.age}' } ] }); } return columns; }; // grid panel Ext.create('Ext.grid.Panel', { id: 'gridpanel', title: 'Fathers', renderTo: Ext.getBody(), width: 600, height: 400, store: Ext.data.StoreManager.lookup('flattenedStore'), columns: buildColumns(maxDaughters) }); }; });
I wonder if the flatten step is needed, it might be possible to achieve the same thing using template columns.
-
5 Jun 2012 7:29 AM #20
I was able to get this working by accessing the child arrays using the template column, with no flatten of the data store needed.
Here is the code,
I think this is a better method then the one suggested by sdt6585, as it doesn't involve building an additional store to handle building the columns. If I could mark this as the best answer I would.Code:Ext.onReady(function() { // models Ext.define('Daughter', { extend: 'Ext.data.Model', belongsTo: 'Father', fields: [ 'age', 'name' ] }); Ext.define('Father', { extend: 'Ext.data.Model', fields: [ 'id', 'married', 'name', 'sons' ], hasMany: 'Daughter' }); // store Ext.create('Ext.data.Store', { storeId: 'fatherStore', autoLoad: true, model: 'Father', proxy: { type: 'ajax', url: 'data1.json', reader: { root: 'fathers' } }, listeners: { load: function(store, records, successful, eOpts) { if (!successful) { return; } var maxDaughters = 0; Ext.Array.forEach(records, function(record) { var number = record.daughters().data.items.length; if (number > maxDaughters) { maxDaughters = number; } }); buildGrid(maxDaughters); } } }); var buildGrid = function(maxDaughters) { // columns var buildColumns = function(maxDaughters) { var columns = [ { xtype: 'rownumberer' }, { text: 'name', dataIndex: 'name' }, { text: 'married', dataIndex: 'married' }, { text: 'sons', dataIndex: 'sons' } ]; for (var i = 0; i < maxDaughters; i++) { var d = 'daughter' + i; columns.push({ text: d, columns: [ { text: 'name', xtype: 'templatecolumn', tpl: '{[values.daughters[' + i + '] ? values.daughters[' + i + '].name : "" ]}' }, { text: 'age', xtype: 'templatecolumn', tpl: '{[values.daughters[' + i + '] ? values.daughters[' + i + '].age : "" ]}' } ] }); } return columns; }; // grid panel Ext.create('Ext.grid.Panel', { id: 'gridpanel', title: 'Fathers', renderTo: Ext.getBody(), width: 600, height: 400, store: Ext.data.StoreManager.lookup('fatherStore'), columns: buildColumns(maxDaughters) }); }; });
It still has the issue where I can't sort the daughter columns.


Reply With Quote