简体   繁体   中英

ExtJS 3.4: How to add a custom renderer dynamically to a PropertyGrid?

I need to display an image in a PropertyGrid. This is usually achieved using the customRenderers config, explicitly overriding the rendered for a specific field:

grid = new Ext.grid.PropertyGrid({
    customRenderers: {
        "picture": function(v)
        {
            return "<img src=\"" + feature.attributes["picture"] + "\" />";
        }
    }
});

But in my case the field on which to apply the custom rendering function is only known at run-time (I have to search for a string like "http:"). But adding the custom renderer dynamically at that time does no seem to work.

Is there any way to do this? Thank you.

Here is how the dynamic property is found:

for (var key in feature.attributes)
{   
    value = feature.attributes[key];
    if ((value != null) && (value.substring(0, 4) == "http"))   
        grid.customRenderers[key] = Function("v", "return \"<img src=\\\"" + value + "\\\" />\";"); 
}

Even though customRenderers is a config property, it is still accessible after the component is created. You can dynamically add them after the grid is created.

Have a look at this jsfiddle: http://jsfiddle.net/Wxx3M/1/

HTML :

<p id="button-container"></p>
<div id="prop-grid"></div>

JS :

Ext.onReady(function(){

    var propsGrid = new Ext.grid.PropertyGrid({
        renderTo: 'prop-grid',
        width: 300,
        autoHeight: true,
        propertyNames: {
            tested: 'QA',
            borderWidth: 'Border Width'
        },
        source: {
            '(name)': 'Properties Grid',
            grouping: false,
            autoFitColumns: true,
            productionQuality: false,
            created: new Date(Date.parse('10/15/2006')),
            tested: false,
            version: 0.01,
            borderWidth: 1
        },
        viewConfig : {
            forceFit: true,
            scrollOffset: 2 // the grid will never have scrollbars
        }
    });

    // simulate updating the grid data via a button click
    new Ext.Button({
        renderTo: 'button-container',
        text: 'Update custom renderer',
        handler: function(){
            var targetProp = null;
            for (var key in feature.attributes)
            {   
                value = feature.attributes[key];
                if ((value != null) && (value.substring(0, 4) == "http"))
                    targetProp = key;   
            }
            propsGrid.customRenderers[targetProp] = function(v){
                return v ? 'XXX' : '';
            }
            propsGrid.getView().refresh();
        }
    });
});

Initially there is no custom renderers. If you click the button, a new dynamic custom renderer is added.

After trying a great deal of different strategies I finally got to something that functions:

grid = new Ext.grid.PropertyGrid();
for (var key in feature.attributes)
{   
    value = feature.attributes[key];
    if ((value != null) && (value.substring(0, 4) == "http"))   
        grid.customRenderers[key] = Function("v", "return \"<img src=\\\"" + value + "\\\" />\";"); 
}

The feature.attributes is a dictionary containing the data to be displayed; a cycle iterates through each of its keys, searching for the fields that might contain image URLs.

There were two key elements that brought me to this solution:

  • Understanding that customRenderers can be used itself as a dictionary, thus dispensing the hard-coding of fields names.

  • The usage of Function as a means to encode the exact value to be rendered, this way avoiding any scope issues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM