Search code examples
extjsextjs3

Unable to render a Ext.form.TextField into the output of an XTemplate


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

  • 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.