4 Comments

Rendering Templates in Ext JS – So Many Choices

html code

Ext JS 4.0 provides a number of ways for custom components to render their HTML content for display. As I have been learning Ext JS, I have often struggled with knowing which technique is the correct one in a given situation. Here I will briefly discuss the different ways of specifying content, followed by some thoughts on when you might want to use them.

Config Options

autoEL

The autoEl config option lets you customize the Element that will encapsulate the Component. By default, all Components are wrapped in a div tag, but autoEl provides a way to specify some other tag. In addition, you can provide HTML that will be rendered inside the Element. For example:

  Ext.create('Ext.Component', {
    id: 'widget',
    renderTo: Ext.getBody(),
    autoEl: {
      tag: 'h3',
      html: '<span>My Content</span>'
    }
  });

will render:

  <h3 id="widget">
    <span>My Content</span>
  </h3>

html

The html config option provides a place for HTML content that will be added after the Component is rendered.

  Ext.create('Ext.Component', {
    id: "widget",
    renderTo: Ext.getBody(),
    html: '<span>My Content</span>'
  });

will render:

  <div id="widget">
    <span>My Content</span>
  </div>

tpl

The tpl config option takes either an Ext.XTemplate or an array of strings that will automatically be converted into an Ext.XTemplate. This is the first option discussed that is a real template, meaning it can contain placeholders that will be replaced with actual values when rendered.

In addition to specifying a template in the tpl config, you also need to provide a data config. It is the initial set of data to apply to the tpl template.

  var widget = Ext.create('Ext.Component', {
    id: "widget",
    renderTo: Ext.getBody(),
    tpl: '<span>Hello {name}</span>',
    data: {name: 'LeVeon'}
  });

will render:

  <div id="widget">
    <span>Hello LeVeon</span>
  </div>

The most powerful feature of the tpl option is that the data can be changed later to update what is displayed on the page. So in the example, to change the name to something else, all that is needed is:

  widget.update({name: 'Bell'});

which will update the content to be:

  <div id="widget">
    <span>Hello Bell</span>
  </div>

It can also be useful to know that if no data config is specified, the Component will be rendered with no inner content, only the containing div. In this case, the update method can still be called later to render the template to the page.

renderTpl

The renderTpl config option is an XTemplate used to create the internal structure inside the Component’s encapsulating Element. It can be either an actual Ext.XTemplate or an array of strings like the tpl option. The Sencha Blog has a good article introducing renderTpl.

renderTpl is coupled with renderData in much the same way that tpl works with data. There appear to be two main differences: (1) The renderTpl will still be rendered if no renderData is specified, and (2) the renderTpl can’t be re-rendered with new data.

  Ext.create('Ext.Component', {
    id: "widget",
    renderTo: Ext.getBody(),
    renderTpl: '<span>Hello {name}</span>',
    renderData: {name: 'LeVeon'}
  });

will render:

  <div id="widget">
    <span>Hello LeVeon</span>
  </div>

Usage

Given all of these options, it’s hard to know when to use each option, especially deciding between tpl and renderTpl. Unfortunately there doesn’t seem to be much documentation or guidance on these matters, at least as far as I have been able to find. The question of deciding between tpl and renderTpl was even brought up in the Sencha Forums a few months ago, but the response from Sencha provided little help:

renderTpl affects the component’s structure. tpl affects the inner html when passing in the data config (or using the update method).

The following are the guidelines I have come up with after working with Ext JS 4.0.x for a few months now.

Static Content

When I need to insert a small amount of static content, I will use autoEl. It lets me specify the outer tag, and it expresses my intention that the content is static. It works particularly well when specifying the items config option for a container.

  items: [
    {
      xtype: 'component',
      autoEl: {
        tag: 'h3',
        html: 'Your Account'
      }
    },
    ...
  ]

The html attribute of the autoEl config takes a single string, so it doesn’t work very well when more than a small amount of HTML is needed.

Dynamic Content

When I need to display dynamic content on the page, especially if it’s data that could potentially be updated on the fly, I use a tpl template. If the data changes later, the update function can be called to re-render the content.

tpl can be provided with an array of strings which it will convert into an Ext.XTemplate automatically. For larger templates, this is much better than trying to put the entire template into a single string in JavaScript. That being said, using an array of strings is an awful way of working with HTML. I am hoping to have some time to work on a way of pre-processing external template files similar to what some have done with Backbone and the Rails Asset Pipeline.

Custom UI Component

When I am making a custom component that’s more of a UI widget than a display of dynamic data, I use renderTpl. This seems to be the right choice because it works with an Ext.XTemplate but doesn’t require a separate data config to be displayed (although you can specify a renderData to apply to the template). In addition, you can specify renderSelectors to automatically add Element properties to the Component after it has been rendered.