PDA

View Full Version : AbstractComponent.tpl not rendered before afterrender fired?



dr-dan
25 Oct 2012, 5:19 AM
I have a component which uses a template.

After the component is rendered, I want to create a further component and renderTo an element in the template. However I notice in the afterrender event the markup of the template is yet to be emitted, so the target el returns null.

Edit in fact its never emitted (see below)

Any advice, best practice for this?



tpl:
new Ext.XTemplate(
'<tpl for=".">',
'<ul>',
'<li class="lang" id="cultureSelector-li"></li>',
'</ul>',

'</tpl>'
),


listeners: {
afterrender: {
fn: function (cmp) {
cmp.mon(cmp.el, 'click', cmp.raiseLinkClicked, cmp);
Ext.create('CultureSelector', {
renderTo: 'cultureSelector-li'
});
}
}
},

dr-dan
25 Oct 2012, 6:16 AM
I ended up having to do the work myself. So, I now have the template as a property called `theTpl`, and then rendered it in `beforerender`, and then i was able to get a handle on the element in `afterrender`. This seems wholly counter-intuitive, does anyone have any insight? Are we supposed to render the template puseselves via update? I was basing this on this post: apparently it's not called. wondering if anything needs to be prompted to trigger it. i was basing this work on this post http://www.sencha.com/forum/showthread.php?114317-Button-In-a-Template&


beforeRender: {
fn: function (me) {
me.update(me.theTpl.apply({}));
}
},

James Goddard
25 Oct 2012, 12:01 PM
You really don't need a template here at all. A template is made to apply data.

For example:


tpl: '<tpl for="."><p>{name}</p></tpl>'
data: [ { name: 'foo', name: 'bar' }]

<p>foo</p><p>bar</p>




tpl: '<ul><tpl for="items"><li>{name}</li></tpl></ul>'
data: {
items: [ { name: 'foo', name: 'bar' }]
}

<ul><li>foo</li><li>bar</li></ul>


Your tpl will not be rendered unless you data is non-null or you call update. Even then, the way your tpl is written, nothing will be rendered unless data is an array with a length of 1 or more. But most importantly since you are doing no data replacement, you should just be using html:


html: '<ul><li class="lang" id="cultureSelector-li"></li></ul>',

dr-dan
25 Oct 2012, 12:21 PM
Ok a couple of things here,

Thanks you just hit the nail for me about data being null. Makes sense now.

In fact id ripped out a lot of the markup which did have runtime replaces. But i was using a generic function from within the template e.g.
<span>{ _localise('logout') }</span> and then also a method on a static class.


{ myApp.helpers.CurrentUserHelper.getFullname() }

i had at first used the data object but this rendered nothing. On testing the template alone with the same data object it was reporting an error - the static didnt exist. So now i set the data object in initComponent. So that i see as a poor pain point - the fact if your template bungs an error it is not reported.

I dont follow why data needs a collection. Surely a set of object properties is suffice?

Seems a lot to second guess there.

James Goddard
25 Oct 2012, 1:33 PM
That's why I gave two examples. One is a collection and the other is an object with a collection in it. You need a collection whenever you use for.

If you have <tpl for="."> as you did in the original example then data itself must be a collection/array.

Generally tpl/data are used for "data view" type of functionality with a store. Recently Sencha has added renderTpl/renderData/renderSelectors which are designed more for specifying an HTML layout for a component. You might want to use those instead since renderSelectors will give you accessors for your elements to use later. I'm not sure if renderTpl requires renderData or not, haven't tried.

James Goddard
25 Oct 2012, 1:58 PM
In answer to my own pondering, no, renderData is not required to use renderTpl. Here's a fiddle that show's how to use renderTpl/renderSelectors:

http://jsfiddle.net/qUudA/7/

dr-dan
26 Oct 2012, 1:02 AM
Great. Thanks for putting me straight.

And for completeness, using renderData as well:

http://jsfiddle.net/qUudA/10/