19 December 2010 ~ 29 Comments

ExtJs renderer

So, you have a column in some sort GridPanel (EditorGridPanel, PivotGrid or a PropertyGrid) that you want to format in a special way and are confused by Sencha Inc’s tecnical documentation  of ExtJs of the renderer property?

We’ll try to sort out some things for you here with simple examples. We’ll use the GridPanel as example, but the can be used pretty much anywhere you want to use the renderer property. Wheter you want to perform a round operation on a number, change the way dates are displayed, add some text. The whole point with the magic renderer config option is to change the way your data is presented.

So, let’s start with some basic stuff. I’ll wrap all this into one single file in the end, so that it will be easy for you to copy&paste.

First we need a datastore with some data to work with, we’ll create en Ext.data.ArrayStore:

        var data = [
            [1,'1980-05-06', 'Nils-Fredrik', 'male', 100],
            [2,'1985-02-26', 'Anders-Meyer', 'male', 100],
            [3,'1960-07-05', 'John Doe', 'male', 10],
            [4,'1961-03-12', 'Jane Doe', 'female', 0]
        ];
        var store = new Ext.data.ArrayStore({
            autoDestroy: true,
            storeId: "myStore",
            idIndex: 0,
            fields: [
                { name: "id", 	 type: "int"	},
                { name: "age",	 type: "date",	dateFormat: "Y-m-d"},
                { name: "name",  type: "string"},
                { name: "sex",   type: "string"},
                { name: "value", type: "int"}
            ],
            data: data
        });

Next we’ll create a simple GridPanel to display the raw data.

        var grid = new Ext.grid.GridPanel({
            renderTo:Ext.getBody(),
            store: store,
            autoHeight: true,
            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age" },
	                { header: "Name",  dataIndex: "name" },
	                { header: "Value", dataIndex: "value" }
                ]
            })
        });

Okay, now we have an ArrayStore with 4 records and 4 fields in each. We also have a GridPanel with 3 columns that should look like this:

Let’s start using the renderer

When working with the GridPanels it’s in the ColumnModel (cm in the config, line 5 in the GridPanel code above above) we do the renderer magic.

First, let’s have a look at the documentation:

“A renderer is an ‘interceptor’ method which can be used transform data (value, appearance, etc.) before it is rendered). This may be specified in either of three ways:

  • A renderer function used to return HTML markup for a cell given the cell’s data value.
  • A string which references a property name of the Ext.util.Format class which provides a renderer function.
  • An object specifying both the renderer function, and its execution scope (this reference)

If not specified, the default renderer uses the raw data value.”

So, we have 4 choices. Either, to leave it alone – and let the raw data be displayed. Use a self declared function, use a predefined function in Ext.util.Format or use an object.
I will cover renderer function and the Ext.util.Format ways in this post.

Renderer function

If you are looking for en example of date format, have a look at my post ExtJs dateformat demystified first.

Let’s first look at how to use a renderer function on the name column:

            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age" },
	                { header: "Name",  dataIndex: "name", renderer: function(value, metaData, record, rowIndex, colIndex, store) {
	                    var returnString = "";
	                    if(record.get("sex") == "male")    returnString += "Mr.";
	                    if(record.get("sex") == "female")  returnString += "Mrs.";
	                    returnString += " "+value;
	                    return returnString;
	                }},
	                { header: "Value", dataIndex: "value" }
                ]
            })

That should produce the following result:

Let’s have a look at this, step by step. As you see, the renderer function takes quite a few parameters:

  • value, the raw value that will be displayed if no renderer is specified.
  • metaData, an interesting object with two properties: metaData.css and metaData.attr.
    The css property will be applied to the cells td element.
    The attr property will be appended to the context container as an attribute string. You could for example specify style=”color: red;”
  • record, a reference to the row record.
  • rowIndex, which row are you at?
  • colIndex, which column are you at?
  • store, a reference to the store used

Let’s try to do some more magic by manipulating the metaData object. Let’s make the womens name red and the mens name blue:

            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age" },
	                { header: "Name",  dataIndex: "name", renderer: function(value, metaData, record, rowIndex, colIndex, store) {
	                    var returnString = "";
	                    if(record.get("sex") == "male")    {
		                    metaData.attr = 'style="color: blue;"';
		                    returnString += "Mr.";
	                    }
	                    if(record.get("sex") == "female")  {
		                    metaData.attr = 'style="color: red;"';
		                    returnString += "Mrs.";
	                    }
	                    returnString += " "+value;
	                    return returnString;
	                }},
	                { header: "Value", dataIndex: "value" }
                ]
            })

This starts getting quite messy. You don’t get a good overview of your code if things are structured like this. Therefore it’s also possible to make the render functions standalone:

        function renderName(value, metaData, record, rowIndex, colIndex, store) {
            var returnString = "";
            if(record.get("sex") == "male")    {
                metaData.attr = 'style="color: blue;"';
                returnString += "Mr.";
            }
            if(record.get("sex") == "female")  {
                metaData.attr = 'style="color: red;"';
                returnString += "Mrs.";
            }
            returnString += " "+value;
            return returnString;
        }
        var grid = new Ext.grid.GridPanel({
            renderTo:Ext.getBody(),
            store: store,
            autoHeight: true,
            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age" },
	                { header: "Name",  dataIndex: "name", renderer: renderName},
	                { header: "Value", dataIndex: "value" }
                ]
            })
        });

You don’t have to care about any other parameters than the value parameter. Lets have a quick look at the age column:

        var grid = new Ext.grid.GridPanel({
            renderTo:Ext.getBody(),
            store: store,
            autoHeight: true,
            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age", renderer: function(date) {return date.format("d.m.Y"); }},
	                { header: "Name",  dataIndex: "name", renderer: renderName},
	                { header: "Value", dataIndex: "value"}
                ]
            })
        });

The above code should produce the following:

This should give you enough to figure the rest of this out on your own. Or what?

Ext.util.Format

The developers of ExtJs has been kind to make a set of often needed renderers available through Ext.util.Format. I am not the biggest fan of Ext.util.Format, but we’ll have a brief look anyway.
Let’s say the value field in our store is a dollarvalue, we can use the currency render and get the result a traditional $way:

        var grid = new Ext.grid.GridPanel({
            renderTo:Ext.getBody(),
            store: store,
            autoHeight: true,
            cm: new Ext.grid.ColumnModel({
                columns:[
	                { header: "#",     dataIndex: "id" },
	                { header: "Age",   dataIndex: "age", renderer: function(date) {return date.format("d.m.Y"); }},
	                { header: "Name",  dataIndex: "name", renderer: renderName},
	                { header: "Value", dataIndex: "value", renderer: "usMoney" }
                ]
            })
        });

That should give us something like this:

Have a look at the docs for more information about Ext.util.Format.

That’s about all I have to say about the renderer by now. You will find the working example with source code http://aboutfrontend.com/examples/extjs-renderer/. If you have any comments or questions, feel free to speak!

Further reading

Professional JavaScript Frameworks: Prototype,YUI, ExtJS, Dojo and MooTools
Beginning PHP RIA Using Extjs
Zend Studio for Eclipse Developer's Guide


http://aboutfrontend.com/2010/12/extjs-gridpanel/

29 Responses to “ExtJs renderer”

  1. Atul 18 September 2011 at 19:12 Permalink

    I am really want to know the mechanism of renderer’s, i have searched many places how to attach custom rendere to the data column and i found it here.

    This is a very useful example to understand rendere and its attachment to the data columns.

    I appreciate the effort of this example.

    Thank you.

  2. maksimer 18 September 2011 at 19:21 Permalink

    @Atul: thank you for your positive feedback!

  3. JViola 22 September 2011 at 18:47 Permalink

    This is a great example of renderers, but what I really need is to render the heading differntly from the detail. For example, how would you center all the column headings, but left justify all the detail data? and not have it conditioned by any value from the the details?
    Thanks.

  4. Nils-Fredrik 23 September 2011 at 09:41 Permalink

    @JViola: That is probably easiest achieved by using css. If you inspect the grid genereated you will see that the head row has a class “x-grid3-hd-row”.
    The following should work:

    div.headrender tr.x-grid3-hd-row td {
       text-align: center;
    }
    
    Ext.onReady(function()	{
    
    var grid1 = new Ext.grid.GridPanel({
        	renderTo:"headrender",
        	store: store,
        	autoHeight: true,
        	cm: new Ext.grid.ColumnModel({
        		columns:[
                    { header: "#",     dataIndex: "id" },
        	        { header: "Age",   dataIndex: "age" },
        	        { header: "Name",  dataIndex: "name"},
        	        { header: "Value", dataIndex: "value" }
        	    ]
        	})
        });
    
  5. maksimer 23 September 2011 at 11:26 Permalink

    @JViola: You also have to remember that this example is ExtJs 3.x not the latest ExtJs 4. I will try to give a ExtJs 4 example as soon as possible.

  6. JViola 23 September 2011 at 14:06 Permalink

    Thank you very much! I will follow your example, it’s exactly what I need.

  7. fifiuro 11 October 2011 at 23:14 Permalink

    Saben que este ejemplo solo sirve para los ExtJS antiguos pero ahora les envio las modificaiones para ExtJS 4 que son las siguientes:

    metaData.att ahora metaData.tdAttr
    metaData.cls ahora metaData.tdCls

    esas son asi que tomen encuenta cuando trabajen con el render.
    chauuuuuuuuuuuuuu

  8. Ankit 23 January 2012 at 18:27 Permalink

    Hi,
    First of all, Thank you so much for the useful post.

    I have a quick question. I want to add a tooltip using a renderer..
    I have added this function –
    renderer: function (value, metadata, record, rowIndex, colIndex, store) {
    metadata.attr = ‘ext:qtip=”‘ + value + ‘”‘;
    return value;
    }

    This gives me a proper tooltip, but –
    1) I need to have it “on top of other things”, (like z-index:1) AND
    2) I need to give it an auto-width.

    It will be great if u can point me a direction.

    Thank you.

  9. Anji 22 March 2012 at 12:19 Permalink

    fantastic explanation………..
    But we want some more complicated Situations with explanation

  10. maksimer 22 March 2012 at 12:46 Permalink

    @Anji: What exactly do you need?

  11. maksimer 22 March 2012 at 12:47 Permalink

    @Ankit: Sorry for the late answer, did you figure it out?

  12. Carlos 26 November 2012 at 01:01 Permalink

    I would like to see how to render a Date coming from a MySQL column datetime.

  13. maksimer 26 November 2012 at 09:54 Permalink

    @Carlos

    If you have a look at my first example here I have defined an array variable, data, containing arrays with the actual data. The second column is a date formated on the format YYYY-mm-dd. Which is the default date format from mysql as far as I know?

    That means you can change the following line:

    { header: “Age”, dataIndex: “age”, renderer: function(date) {return date.format(“d.m.Y”); }},

    in the last example to produce any output you want?

  14. Carlos 26 November 2012 at 17:24 Permalink

    Thanks, I will try your suggestion. Overall your blog is fantastic!

  15. maksimer 26 November 2012 at 19:23 Permalink

    Thanks for your positive feedback. The posts are quite old now. Will be doing quite a lot of Ext the next months, so you will probably see some updates. 🙂

  16. Pri 4 March 2013 at 20:39 Permalink

    Just started off with ExtJs and Sencha was so difficult to follow.
    This is just AWESOME and nicely explained.

    Thanks a Ton!

  17. Carlos Crosetti 4 March 2013 at 23:18 Permalink

    I think Sencha Architect is a good product however I think it nedds a copule of improvements.

    1. the component attribute panel is docked at the right side and must be floating, alowing more space to the canvas.

    2. The same panel must have rezizable fonts, it is too small what I seee.

    3. If I want to have multiple windows being edited, ther swhould be a clear separation between them.

    4. The default visibility for the window at design time is disabled, so when you previwe nothing is seen, I spent many hours before solving this.

    5. The Eclipse integration must be deleloped a bit more and documented, It wwas truly painful for me making a UI coming from Architect into an existing Eclipse workspaace.

    Carlos

  18. mobile games cheats 3 April 2014 at 10:06 Permalink

    Hi there! Do you use Twitter? I’d like to follow you if that would
    be ok. I’m definitely enjoying your blog and look forward to new
    updates.

  19. telecharger malwarebytes 20 April 2014 at 17:49 Permalink

    Hi there, I found your blog by way of Google at
    the same time as looking for a similar topic, your website got here
    up, it looks great. I have bookmarked it in my google bookmarks.

    Hi there, just became alert to your weblog via Google, and found that it’s really informative.

    I am gonna be careful for brussels. I will appreciate if
    you proceed this in future. Lots of folks will likely be benefited out of your writing.
    Cheers!

    Feel free to surf to my webpage – telecharger malwarebytes

  20. castle clash hack android 13 May 2014 at 14:42 Permalink

    I don’t even know the way I finished up right here, however I believed this publish used to be good.
    I don’t know who you’re but definitely you are going to a well-known blogger for those who are
    not already. Cheers!

    Look into my web blog; castle clash hack android

  21. jetpack joyride hack apk 17 May 2014 at 12:54 Permalink

    Unquestionably believe that which you said.
    Your favorite reason appeared to be on the web the easiest thing to be
    aware of. I say to you, I definitely get irked
    while people consider worries that they just don’t
    know about. You managed to hit the nail upon the top and defined out the
    whole thing without having side effect , people can take a signal.
    Will likely be back to get more. Thanks

    My site – jetpack joyride hack apk

  22. My developer is trying to convince me to move to .net from
    PHP. Ihave always disliked the idea because of the costs.

    But he’s tryiong none the less. I’ve been using WordPrress on a number of websites for about a year and am worried about switching to
    another platform. I have heard gdeat things about blogengine.net.
    Is there a way I can transfer all my wordpress posts into it?
    Any kind of help would be really appreciated!

  23. laras 23 September 2014 at 08:44 Permalink

    Wooooow. wonderful. i’m new comer in ext.js… i have searching on and on this case and finally found here…

    Many thanks dude 🙂

  24. Coach Hire Hitchin 12 October 2014 at 22:40 Permalink

    Hi there, just became alert to your blog through Google,
    and found that it is truly informative. I’m gonna watch out for
    brussels. I will appreciate if you continue this in future.
    Numerous people will be benefited from your writing.
    Cheers!

  25. Student Kitchen Starter Pack 20 October 2014 at 12:05 Permalink

    Magnificent items from you, man. I have keep in mind youhr stuff previous to
    and you’re just extremely great. I actually like what you have obtained
    here, certainly liike what you’re stating and
    the best way by which you say it. You are makijg it enjoyable and you still care for to keep it sensible.
    I cant wait to learn much more from you. That is really a tremendous web site.

    My page – Student Kitchen Starter Pack

  26. LuisHilario 23 June 2015 at 17:31 Permalink

    GRACIAS ME AYUDO MUCHO

  27. Akila 12 October 2015 at 12:10 Permalink

    Hi,
    i have doubt for how load the grid from XML data with out using JSON in extjs6..

  28. Akila 12 October 2015 at 12:13 Permalink

    Hi,
    i have doubt how load the grid from XML data with out using JSON in extjs6..

    using store like this,

    var eioaGridStore = new Ext.data.XmlStore({
    model: ‘Task’,
    autoLoad: true,
    proxy: { type: ‘memory’,reader: { type: ‘xml’, root: ‘Interfaces’, record: ‘Interface’,
    idProperty: ‘taskId’
    }
    }

  29. Bing 1 March 2016 at 15:52 Permalink

    Pretty! This was an incredibly wonderful article.
    Thanks for providing these details.


Leave a Reply