Write my own decorator
This tutorial will take you through the process of creating a new decorator to add to a grid, in order to extend its basic functionality. Just as an example, what we’re going to do is create a decorator that will add or remove a CSS class to a row when it is clicked, prompting a background colour change.
Step 1: Adding the Decorator to the Grid Definition
We’ll start off by defining an alias for our new decorator. We will do this inside the resources folder at the bladeset level as we are defining an alias that didn’t exist before. The decorator won’t work at this point, because it doesn’t exist yet, but it at least lets us know what we are aiming at:
<aliasDefinitions xmlns="http://schema.caplin.com/CaplinTrader/aliasDefinitions">
<alias name="novox.myDecorator"
defaultClass="novox.fxtrader.grid.decorator.MyDecorator">
</alias>
</aliasDefinitions>
Once we’ve got our newly defined alias, we need to add it to a grid. Note that the alias is used as an XML element, and we’ve given it an attribute of its own: clickedClass
. That will contain the name of the CSS class that we will be adding or removing from the grid row.
<grid id="myGrid">
<decorators>
<novox.myDecorator clickedClass="<name of the class>" />
</decorators>
</grid>
Having done that, we need to create our new decorator.
Step 2: Creating a Decorator Class
First of all, we need to create a decorator class, which will implement the caplin.grid.decorator.GridDecorator
interface. You can do this as follows:
caplin.implement(novox.fxtrader.grid.decorator.MyDecorator, caplin.grid.decorator.GridDecorator);
Note that the first argument in caplin.implement()
matches the className
attribute from the <decoratorMapping>
tag in our grid definition.
Our class’s constructor will receive the decorator’s configuration as a parameter. We can use this to get any parameters from the XML configuration file; in this case, we need our decorator to get hold of the CSS class that we specified in the XML.
novox.fxtrader.grid.decorator.MyDecorator = function(mDecoratorConfig)
{
this.clickedClass = mDecoratorConfig.clickedClass;
};
So now we have a new grid decorator, with the highly original name of "MyDecorator", and it has the name of the CSS class it will be using. Now all we need is for it to actually do something.
Step 3: Registering the Decorator as a Listener
As the "something" that we want it to do, should happen when we click on a grid row, our next task is to make sure that the decorator knows when that has occurred. Caplin provides various "listeners" to do that job for us, all we have to do is subscribe to them; first by registering for events that occur on the grid container, and then to specifically listen for click events.
To register ourselves as listeners to the grid elements we are interested in, we use the implemented method setGridView()
. Bear in mind that the grid would not have yet been rendered at this point. For full details of all the elements that you can register on, have a look at caplin.grid.decorator.GridDecorator
in our Grid API reference section. We want to listen to events on the grid container, so we’ll implement the caplin.grid.GridViewListener
interface, as shown below:
caplin.implement(novox.fxtrader.grid.decorator.MyDecorator, caplin.grid.GridViewListener);
// GridDecorator Interface Methods
novox.fxtrader.grid.decorator.MyDecorator.prototype.setGridView = function(oGridView)
{
// register the decorator as a listener
this.m_oGridView = oGridView;
oGridView.addGridViewListener(this);
};
Step 4: Subscribing to Events
Having registered as a listener to grid view events (and you can see a complete list of what grid events you can listen for, at caplin.grid.GridViewListener
in the Grid API reference section) we want to subscribe specifically to click events that occur on the grid container. Once the grid is rendered, we’ll register one of our methods as a handler for click events happening on the grid container:
// GridViewListener Interface Methods
novox.fxtrader.grid.decorator.MyDecorator.prototype.onContainerHtmlRendered = function()
{
this.m_eRowContainer = this.m_oGridView.getRowContainerElement();
// Subscribe to the click event happening on the row container
// and handle it with our _onClick method
this.m_nClickListenerId = caplin.dom.Utility.addEventListener(this.m_eRowContainer, "click", this._onClick.bind(this));
};
Refer to caplin.dom.Utility
in the API reference, for further details.
Step 5: Handling Events
Now we’re subscribed to the grid container’s click events, we need to define how we’re going to handle them when they occur. We’ll implement our _onClick()
handler, determine the row in which the click has taken place and check if it has the CSS class we defined. If it already does, we’ll remove it; otherwise we’ll add it.
novox.fxtrader.grid.decorator.MyDecorator.prototype._onClick = function(oEvent)
{
oEvent = caplin.dom.event.Event.getNormalizedEvent(oEvent);
var eRow = caplin.dom.Utility.getAncestorElementWithClass(oEvent.target, "row");
if(caplin.dom.Utility.hasClassName(eRow, this.clickClass)) {
caplin.dom.Utility.removeClassName(eRow, this.clickClass);
} else {
caplin.dom.Utility.addClassName(eRow, this.clickClass);
}
};
Refer to caplin.dom.event.Event
and caplin.dom.Utility
in the API Reference for full details of the events and utilities used here.
Step 6: Housekeeping
That more or less completes the basic functionality, but before we put our feet up and have a well-earned cup of tea, there is one last thing to do: remove ourselves as event-listeners on the grid view after it’s been closed. There’s a specific method from the caplin.grid.GridViewListener
interface that enables us to do so: the onClose()
method, which is triggered when the view is closed.
novox.fxtrader.grid.decorator.MyDecorator.prototype.onClose = function()
{
// Clean up
caplin.dom.Utility.removeEventListenerById(this.m_nClickListenerId);
this.m_eRowContainer = null;
};
And here is the result: The clicked rows now have a red background colour.