PDA

View Full Version : [FIXED-EXTJSIV-264] Combo Templates



c2c-guinness
22 Mar 2011, 6:28 PM
I've not been able to get combo templates to work using 'tpl' .. maybe I'm doing that wrong or something has changed.

Either way though, something is broken in Ext as the example doesnt work. Look at the second combo, custom item templates. An abbreviation should be showing up there, and is not:

http://dev.sencha.com/deploy/ext-4.0-pr5/examples/form/combos.html

jjohnston
23 Mar 2011, 6:32 PM
The old 'tpl' config has been changed, now you supply a getInnerTpl function as part of the listConfig configuration. The combos example was not updated to match this change (we're on it.)

I'm looking into the sorting issue.

c2c-guinness
24 Mar 2011, 9:56 AM
I was trying to figure out what you meant by "listConfig". I notice the example does use innerTpl, and I'm guessing it should go inside of listConfig: {} but I could not find any reference to that.

Since the PR5 combo documents are broken I was looking at PR4 but listConfig is not indicated.

Could you please provide a quick example usage?

Thanks,
Luke

c2c-guinness
24 Mar 2011, 10:01 AM
Nevermind, I suppose it is as easy as it sounds:




this.myCombo = Ext.createWidget('combo', {
...
listConfig: {
getInnterTpl: function() {
return "<div>... etc ...</div>";
}
}
});



But what about the combo display template? The value in the combo when the list is not expanded?

jjohnston
24 Mar 2011, 10:03 AM
Yup, you got it. :) Sorry about the broken docs formatting, we're fixing that. In the meantime you can click through to the source code (click the class name at the top of the doc page) and read the doc comments in there.

adamb500
3 May 2011, 8:01 AM
Does this mean we have to return a string and not an XTemplate now?

mberrie
11 May 2011, 11:47 AM
Yes, the returned String will be part of an XTemplate definition, see Ext.view.BoundList:55



me.tpl = Ext.create('Ext.XTemplate',
'<ul><tpl for=".">',
'<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
'</tpl></ul>'
);


The default implementation just renders the displayField:

getInnerTpl: function(displayField) {
return '{' + displayField + '}';
},



Currently I can't see a good way to override the entire template definition (tpl) which was possible in Ext3.

One should also not get confused by the docs inherited from AbstractView - itemTpl and tpl config options do not apply to BoundList since it overrides base class functionality as shown above.

stevil
11 May 2011, 12:06 PM
Currently I can't see a good way to override the entire template definition (tpl) which was possible in Ext3.



It's not very clean, but you could do:

1) Extend BoundList
2) Override initComponent
3) this.callParent(), then set this.tpl to a new XTemplate based on




me.tpl = Ext.create('Ext.XTemplate',
'<ul><tpl for=".">',
'<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
'</tpl></ul>'
);



4) Extend ComboBox
5) override CreatePicker to basically copy it, and change the Ext.create for the picker to use your BoundList as the picker


HTH

stevil

stevil
11 May 2011, 12:08 PM
Or, if you want this everywhere, you could just override BoundList and ComboBox. Easier, but not long on style points...

stevil

mberrie
11 May 2011, 12:49 PM
Thx for your reply.

Both solutions massively violate my coding conduct :)

When I ran into this yesterday, I decided to rewrite my CSS and go with the standard markup instead. Everything else gave me the willies.

Haven't even looked as far as how to use a custom BoundList implementation in ComboBox. There should really be an easy way to override the implementing class when using composition. Duplicating the createPicker code could easily be avoided if the code delegated instantiation to a factory method , or - facilitating the Ext4 class loading pattern - just allow configuration of the class name as a config property.

Admittingly, reconfiguring the tpl in BoundList after callParent wouldn't be THAT bad - just not very nice since we execute code and then throw away the result.

stevil
11 May 2011, 1:05 PM
Both solutions massively violate my coding conduct :)



I'm morally flexible.

stevil

mberrie
11 May 2011, 8:45 PM
I guess I would duplicate the BoundList#initComponent in a 'global' override to BoundList and adapt the code to check for a preconfigured tpl property.

This way one could just define the template on the combo box via a listConfig.tpl config property.


if(!me.tpl) {
me.tpl = Ext.create('Ext.XTemplate',
'<ul><tpl for=".">',
'<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
'</tpl></ul>'
);
}
AbstractView#initComponent already has code to 'convert' String and Array values into a propert XTemplate instance.

AbstractView:178

if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
me.tpl = Ext.create('Ext.XTemplate', me.tpl);
}

The code has to be maintained upon every new release of Ext - I guess that Ext might allow for something like this in one of the future releases anyway.





Picking up on your idea to just reset the tpl property AFTER the default implementation, I've come up with this override.


/**
* Allow for overriding the list template in a ComboBox by defining tpl as
* part of the {@link Ext.form.field.ComboBox#listConfig}.
*
* listConfig : {
* tpl : [
* '<ul><tpl for=".">',
* '<li role="option" class="x-boundlist-item">{aModelProperty}</li>',
* '</tpl></ul>'
* ],
* }
*
* This will reintroduce the behavior described in {@link Ext.view.AbstractView#tpl}, but
* not support {@link Ext.view.AbstractView#itemTpl}. If tpl is configured,
* {@link Ext.view.BoundList#getInnerTpl} does not apply. Furthermore, make sure the
* configured tpl applies the {Ext.view.BoundList#itemCls} to all list items otherwise
* standard list behavior will fail.
*
* This is of course a hack since the default implementation of {@link Ext.view.BoundList#initComponent}
* will still create a template and call {@link Ext.view.BoundList#getInnerTpl}, but the resulting
* template instance will be subsequently trashed.
*
* There are other solutions to this, see http://www.sencha.com/forum/showthread.php?127714-FIXED-EXTJSIV-264-Combo-Templates
*/
Ext.override(Ext.view.BoundList, {
initComponent : function() {
// cache the configured tpl property before default implementation overwrites it
var tpl = this.tpl;
this.callOverridden();
if(tpl) {
// String and Array processing
if(Ext.isString(tpl) || Ext.isArray(tpl)){
tpl = Ext.create('Ext.XTemplate', tpl);
}

// reassign cached tpl
this.tpl = tpl;
}
}
});

stevil
12 May 2011, 4:27 AM
Yeah, it's not pretty, but it will work.

I think they should expose a listConfig for ComboBox that allows AT LEAST the component type for the list, and also its template to be supplied. Then you'd have no overrides required.

stevil

mberrie
19 May 2011, 3:07 AM
EDIT: this is not fixed in 4.0.1 - I got confused with my own changes I've made to the Ext source *blush*


------
This is what IMHO should be possible.



listConfig : {
tpl : [
'<ul><tpl for=".">',
'<li role="option" class="x-boundlist-item">{aModelProperty}</li>',
'</tpl></ul>'
],

// or

tpl : Ext.create('Ext.XTemplate', '...'),

// or

tpl : '<ul><tpl for="."><li role="option" class="x-boundlist-item">{aModelProperty}</li></tpl></ul>',
}


Any override to 'getInnerTpl' will no longer be considered in this configuration. Furthermore, the rendered list will not automatically default to the configured 'displayField'.
------


EDIT: I have filed a bug/feature request with suggested changes (and a patch that implements those changes) here:

http://www.sencha.com/forum/showthread.php?134287-4.0.1-Improvements-to-ComboBox-and-BoundList

mitchellsimoens
29 May 2011, 8:01 AM
I have submitted a change that is awaiting approval for the 4.0.2 release. I have verified it works for my test cases and an app I am currently building. If it does get approved, I will update this post.