Technical solutions and general life savers

ExtJs 3.4 – Using XTemplate – Basics

ExtJs has a whole range of useful components, but sometimes a more appealing interface object is required or one that is lighter to render. ExtJs provides you with a function that makes it easier to basically make anything you want within the limits of HTML and CSS.

Traffic light example
For this article I will use a component we use to illustrate risk within our application in the form of a traffic light. I will extend this example step by step to give you an idea how to design a control from the ground up and give you a feeling on how easy it can be.

If you are searching for more in dept information about how to create any kind of control try “Using XTemplate – Advanced” article.

Note: I will declare all variables in global space to make the example easier to read and try out. Using it like this is strongly discouraged as it will NOT provide any data layer abstraction. So when you got 1000+ variables inside your applicition, you are bound to override one that is used by another part of the application. When I got the time I will provide you with an article that explains this more in dept and provides you with solutions.

Setup XTemplate: Hello world
This example will output an Ext.Window that shows hello world as content.

1

2

3

4

5

6

7

8

trafficLight=newExt.Window({

height:100,

width:100,

template:newXTEmplate('Hello world'),

data:{}

})

trafficLight.show();

I agree, you can achieve the same with the HTML tag or by adding an element with that text. So lets make it more dynamic.
Now add message: ‘hello this world’ to the data object and replace hello world in the template with {message}

1

2

3

4

5

6

7

8

9

10

trafficLight=newExt.Window({

height:100,

width:100,

template:newXTemplate('{message}'),

data:{

message:"Hello this world"

}

})

trafficLight.show();

Now the message shown is read from the data object provided. This works because this behavior is inherited from Ext.Component. When tpl and data are provided, it will attempt to fill the given element with these 2 variables on render.

Now their are 2 ways to move forward. You can either call overwrite on the tpl, supply the target and data directly or call update on this component by providing the data needed. I will show you both. But first we need to split off the data object, because in a window the property ‘data’ it is not available after render. This while we want it to know what the previous state of the window was.

1

2

3

4

5

6

7

8

9

10

11

12

trafficLightData={

message:"Hello this world"

}

trafficLight=newExt.Window({

height:100,

width:100,

template:newXTemplate('{message}'),

data:trafficLightData

})

trafficLight.show();

Call update on component
There, now the easiest way is the following which uses the internal update function to handle the request.

1

2

trafficLightData.message="Goodbye and thank you for all the fish";

trafficLight.update(trafficLightData);

Call overwrite on the template
Although the following example is more ‘difficult’ and does not provide extra functionality in this example. I would like to show it to you because you can use it to apply one template to multiple components. Because it uses element as a target you can apply a template to Objects that are not inherited from Component.

1

2

trafficLightData.message="Goodbye and thank you for all the fish";

trafficLight.tpl.overwrite(trafficLightData.body,trafficLightData);

In short what I do is call overwrite on the Template, the same method used by update(), but provide the target myself. Which is Window.Body, the element that shows the content part of a Window.
Note that this only works when the Window is rendered as the body element is created then.

Example adaptive render
Now this does not at all look like a traffic light. So let’s change that.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

trafficLightData={

color:"red"

}

trafficLight=newExt.Window({

height:100,

width:100,

tpl:newExt.XTemplate(

'<strong>',

'<div style="color: red;">&bull;</div>',

'<div style="color: orange;">&bull;</div>',

'<div style="color: green;">&bull;</div>',

'</strong>'

)

})

trafficLight.show();

Wow, what is all this?
Well first is the template: When you keep adding string as parameters, these will be appended to the template. So this makes it a lot more readable. Then I have added 3 bullets using HTML entity &bull; • and put them in to div as the conveniently puts them on new lines.

Next, let’s make the component show the actual value, which is red as shown in trafficLightData.

Now this is one of the more interesting things of a template. When is used, you can add logical expressions, loops and functions in the template. In this example I use IF. Now inside the if attribute I have put “color==\’red\’”.
When a value is not inside ” it is seen as a variable that it will try to get from the data object. When put between ” it becomes a string you can use to compare. So this is essentially a simple if construction, that adds ‘ font-size: 20px;’ to the style attribute of the div when true.

Example click events
Now it makes the red light show up on default, but we want it to change dynamically, on click for example. So let’s do that first.

Although not very elegant this will make the traffic light switch from red -> green -> orange -> red. This is achieved by making an event click on Window.body which is created after render of the Window. Then the colorSwitch object is used to retrieve the next value. Then update() is called with the updated value.

Now to make a more useful component out of this you probably want to click the color you would like to select and be able to retrieve it.

This requires the following, you need to know which element has been clicked. You can make a listener for every rendered element, but this is heavier and in my opinion not a very nice solution. Instead we introduce our own attributes on the rendered elements. And let this same event return the element that was clicked.

Et voila. As the data object holds the actual value that can be used to identify the current state of the Component and the Component shows the correct state.

Optional improvements
To make this component more useful it needs a couple of things.

Use a Component or Panel as you base instead of Window, it’s more easily usable inside layouts. You might even want to consider using Ext.form.Field as a base is even lighter.

Give it fixed height and width, else you need to redesign the layout to scale.

You can also make it dynamic by being able to add any colors by a config option.

Expose something like an setValue and GetValue so you don’t have to fiddle with the data object and Update(). You might also want to expose an onValueChange() or similar event.

You can use background-color or border color to make the selection more visible and use a pointer on the values to make it appear clickable.Note: CSS code with Internet Explorer ‘hack’
cursor:pointer;cursor:hand

Final thoughts
Making a component like this is (arguably) easy. This is one of the things that make ExtJs stand out as it gives you tools, but also the possibility to easily extend on those tools to suit them for your needs. To actually create a new component you might want to look at our tutorials we have about extending and creating new components.

The possibilities of XTemplate are not exhausted by a long shot, see my article about advanced XTemplating to get a grip on those. But in the mean time, I hope you have been able to follow up on my rambling and have a grasp on the basic concept of the XTemplate.