-
12 Dec 2011 12:45 AM #1
Answered: Call custom function in Group Header Template
Answered: Call custom function in Group Header Template
I use custom renderers in my grid to display data I get from another store.
One of them is:
Now I'm grouping my store of the grid and trying to customize the group titles:Code:function genre_name(val) { return genres.queryBy(function(rec) { return rec.data.id == val; }).get(0).get('genre'); }
However I get an error: Uncaught SyntaxError: Unexpected identifierCode:var groupingFeature = Ext.create('Ext.grid.feature.Grouping', { groupHeaderTpl: 'Genre: {[genre_name({name})]}' });
Even if I enter the parameter directly in the template like this
I get another error: Uncaught ReferenceError: genre_name is not definedCode:var groupingFeature = Ext.create('Ext.grid.feature.Grouping', { groupHeaderTpl: 'Genre: {[genre_name(1)]}' });
Why is it not possible to call the function genre_name() although it's being called by the grid for the renderer function for each column. Or is there any way I can access the values generated by the renderer function of the grid?
-
Best Answer Posted by skirtle
Taking these one at a time.
First, this:
I assume genres is a store?Code:function genre_name(val) { return genres.queryBy(function(rec) { return rec.data.id == val; }).get(0).get('genre'); }
For the line rec.data.id, generally it is bad practice to access a field through the data property, use rec.get('id') instead.
Using queryBy seems excessively complicated for finding a single record. Would it not be easier just to use findRecord?
Assuming id is the idProperty for your model, it would probably be even easier to use getById.Code:function genre_name(val) { return genres.findRecord('id', val).get('genre'); }
Next, this:Code:function genre_name(val) { return genres.getById(val).get('genre'); }
The code inside {[...]} will just be run as JavaScript, no substitutions can be made. This is why you get that error as {name} isn't valid JavaScript.Code:{[genre_name({name})]}
Inside a {[...]} block you have access to a number of useful variables such as values and parent. Take a look at the docs for XTemplate for more information:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.XTemplate
Next up, this one:
If genre_name is a global function then this will work fine. Given the error you're seeing I can only conclude that genre_name isn't global and that your grid is in the right scope to see it. This is actually a good thing, you shouldn't have globals without a suitable namespace.Code:{[genre_name(1)]}
To call a formatting function you have a few options. One option is to save it in the formats namespace:
The reason for doing this is that formats have a special syntax within templates:Code:Ext.util.Format.genre_name = function() { ... };
An alternative is to save the function on the template itself:Code:{name:genre_name}
Personally I'd usually go for this last option but if your formatting function is used throughout your application then saving it to Ext.util.Format would make it much easier to share it.Code:groupHeaderTpl: Ext.create('Ext.XTemplate', 'Genre: {name:this.genre_name}', { genre_name: function(val) { ... } });
-
12 Dec 2011 4:39 AM #2
Taking these one at a time.
First, this:
I assume genres is a store?Code:function genre_name(val) { return genres.queryBy(function(rec) { return rec.data.id == val; }).get(0).get('genre'); }
For the line rec.data.id, generally it is bad practice to access a field through the data property, use rec.get('id') instead.
Using queryBy seems excessively complicated for finding a single record. Would it not be easier just to use findRecord?
Assuming id is the idProperty for your model, it would probably be even easier to use getById.Code:function genre_name(val) { return genres.findRecord('id', val).get('genre'); }
Next, this:Code:function genre_name(val) { return genres.getById(val).get('genre'); }
The code inside {[...]} will just be run as JavaScript, no substitutions can be made. This is why you get that error as {name} isn't valid JavaScript.Code:{[genre_name({name})]}
Inside a {[...]} block you have access to a number of useful variables such as values and parent. Take a look at the docs for XTemplate for more information:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.XTemplate
Next up, this one:
If genre_name is a global function then this will work fine. Given the error you're seeing I can only conclude that genre_name isn't global and that your grid is in the right scope to see it. This is actually a good thing, you shouldn't have globals without a suitable namespace.Code:{[genre_name(1)]}
To call a formatting function you have a few options. One option is to save it in the formats namespace:
The reason for doing this is that formats have a special syntax within templates:Code:Ext.util.Format.genre_name = function() { ... };
An alternative is to save the function on the template itself:Code:{name:genre_name}
Personally I'd usually go for this last option but if your formatting function is used throughout your application then saving it to Ext.util.Format would make it much easier to share it.Code:groupHeaderTpl: Ext.create('Ext.XTemplate', 'Genre: {name:this.genre_name}', { genre_name: function(val) { ... } });
-
16 Dec 2011 11:53 AM #3
Thank you very much for your detailed instructions on improving my code and solving the formatting problem. I adapted your changes and the display of the genre name works as intended now by saving my function in the Ext.util.Format namespace.
I also tried your second solution and created a XTemplate with my function inline:
However this does not work and [object Object] gets displayed as the group header. As the other solution works, it's not important to know why this doesn't work, I'm just curious why ExtJS won't call the inline formatting function.Code:var groupingFeature = Ext.create('Ext.grid.feature.Grouping', { groupHeaderTpl: Ext.create('Ext.XTemplate', 'Genre: {name:this.genre_name}', { genre_name : function(val) { var rec = genres.getById(val); return rec ? rec.get('genre') : val; } }) });
-
16 Dec 2011 4:21 PM #4
OK, having done a quick bit of digging I think I can explain it. From the docs for groupHeaderTpl:
It does string concatenation internally with the provided string, so the XTemplate I created was treated as a string, giving what you described. In general the approach I suggested works fine with an XTemplate, it's just the way its used with that config option requires it to be a string rather than the template itself.Template snippet, this cannot be an actual template.
-
18 Dec 2011 2:38 AM #5
Thank you for the clarification, it worked after I modified the Template to:
I also found an interesting solution here: http://www.sencha.com/forum/showthre...d-column-titleCode:groupHeaderTpl: 'Genre: {name:genre_name}', genre_name : function(val) { var rec = genres.getById(val); return rec ? rec.get('genre') : val; }
This solution overrides the Ext.grid.feature.Grouping to also return the title of the group and its rendered value.
-
27 Aug 2012 8:04 AM #6
i was not able to use inline methods with INPUT element:
Button this.groupSelect not fired. The section before colon simply executed fine.Code:items: { xtype: 'grid', selModel: Ext.create('Ext.selection.RowModel', { listeners: { select: {fn: me.rowSelect, scope: me } } }), features: [ Ext.create('Ext.grid.feature.Grouping',{ groupHeaderTpl: Ext.create('Ext.XTemplate',' {[this.groupSelect()]}: <input type="button" onclick="this.groupSelect" value="select"> {name} ', { groupSelect: function(value) { console.log('tpl grp sel: '+value); } } ), startCollapsed: false, enableGroupingMenu: false, collapsible: false })], columns: [ ... ] ...
any hints?
Thx


Reply With Quote