I want to render some Ext components into the output of an XTemplate
. We want to have the flexibility of using an XTemplate
to render the HTML but retain the styling, behaviour, and handlers of using Ext components rather than plain old HTML elements.
I am currently successfully doing this with an Ext.Button
. In the template I am writing a placeholder div like so:
<div id="paceholder-1"></div>
After I have called apply()
on the template I then create a new Ext component and render it in like so:
this._replacePlaceholders.defer(1, this, [html, 'placeholder-1', collection]);
The _replacePlaceholders
function looks like this:
_replacePlaceholders: function(html, id, collection) {
var emailField = new Ext.form.TextField({
emptyText: 'Email address',
hideLabel: true
});
var downloadButton = new Ext.Button({
text: 'Download as...',
icon: 'images/down.png',
scope: this,
menu: this._createDownloadOptionsMenu(collection) // Create Menu for this Button (works fine)
});
var form = new Ext.form.FormPanel({
items: [emailField, downloadButton]
});
downloadButton.render(html, id);
}
This works and renders the button into the html correctly. The button menu behaves as expected.
But if I change the last line of replacePlaceholders
to emailField.render(html, id);
or form.render(html, id);
I get a javascript error.
TypeError: ct is null
ct.dom.insertBefore(this.el.dom, position);
ext-all-debug.js (line 10978)
I'm a bit confused because from what I can tell from the docs the render()
method called is going to be the same one (from Ext.Component
). But I've had a bit of a play around and can't seem to track down what is happening here.
So is there any good reason why these components behave differently from Ext.Button
? and is it possible to render an Ext.form.TextField
or an Ext.form.FormPanel
or anything that will let me use an Ext text field in mt XTemplate html?
NB. I am using ExtJS 3.3.1 and don't have the opportunity to upgrade the version. I believe ExtJS 4 has functionality which would make doing what I doing much easier.
Thanks!
Solution is quite simple - use form.render(id)
instead of form.render(html, id)
.
See [api][1] if you have doubts.
The reason why button is rendering properly is that it has weird onRender
implementation, different from Component
.
onRender : function(ct, position){
[...]
if(position){
btn = this.template.insertBefore(position, targs, true);
}else{
btn = this.template.append(ct, targs, true);
}
[...]
}
As you can see in code above, if you provide position (which is basically second argument provided to render
) it doen't use ct
(which is first argument passed to render
).
In normal component onRender
method looks like this:
onRender : function(ct, position){
[...]
if(this.el){
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
if (div) {
Ext.removeNode(div);
div = null;
}
}
}
}
In code above, you can see, that ct
is called always, despite the position is not null.
The bottom line is that rendering of button works by accident.