Rendering Templates in Ext JS – So Many Choices

 

“Ext JS 4.0”:https://www.sencha.com/products/extjs/#overview 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.

h2. Config Options

h3. 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: 'My Content'
    }
  });

will render:

My Content

 

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: 'My Content'
  });

will render:

My Content

 

h3. 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: 'Hello {name}',
    data: {name: 'LeVeon'}
  });

will render:

Hello LeVeon

 

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:

Hello Bell

 

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.

h3. 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”:http://www.sencha.com/blog/whats-new-in-ext-js-4-1/.

@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: 'Hello {name}',
    renderData: {name: 'LeVeon'}
  });

will render:

Hello LeVeon

 

h2. 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”:http://www.sencha.com/forum/showthread.php?190974-tpl-and-renderTpl-use-cases&langid=1 a few months ago, but the response from Sencha provided little help:

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

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

h3. 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”:http://patshaughnessy.net/2011/6/28/where-does-my-javascript-code-go-backbone-jst-and-the-rails-3-1-asset-pipeline.

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

Conversation
  • AlexN says:

    What would you recommend to use in the case when there is a mix of Extjs3 and 4 applications that need to have at least common header with menu and footer?

    • Patrick Bacon Patrick Bacon says:

      Alex,

      We have a similar situation on the application I am currently working on. We have the application server render the header and footer to the page, so it doesn’t matter whether it is an Ext 3 or an Ext 4 page.

      If you need the header and footer to be controlled by Ext I think you should still render them server-side and then use the contentEl config option. With this config you specify the ID of an element that has already been rendered to the page (most likely hidden to start).

      The documentation indicates that the contentEl config is supported in both Ext 3 and 4.

      • AlexX says:

        Thank you, will give it a try today.
        So far I’ve been experimenting with explicitly putting content into extra “center” region of bare container between, “north” and “south” areas which load their content from dynamic Apache SSI/.shtml using containers’ loader config with url and autoLoad properties.

      • AlexN says:

        Tried contentEl, however the html content that it pulls is added after a component renders itself; I have also tried “renderTo” – does not seem to work on at least predefined index.html with header, footer and the main content placeholders where the main view port or even regular container is supposed to appear.

  • Comments are closed.