ExtJS - zero safe extraction of complex objects using JsonReader

I use JsonReader to map Json data to variables that will be used in the grid / form. The back end is in Java, and there are complex objects that I Jsonify and go to ExtJS frontend. This is the part of my JsonReader that is trying to retrieve a nested object -

{name:'status', type: 'string', mapping: 'status.name'}

This works fine when the status matters (but not on the server), but the grid failure with the status is zero. Currently, the work around me is to send an empty object from the server in case of null, but I suppose there should be a way to handle this in ExtJS. Please suggest the best solution on the ExtJS side.

+3
source share
3 answers

: :

  • convert() - Ext.data.Field:

    {
        name:'status', 
        mapping: 'status',
        convert: function(status, data) {
            if (!Ext.isEmpty(status) && status.name) {
                return status.name;
            } else {
                return null;
            }
        }
    }
    
  • mapping ( , , , ):

    {
        name:'status', 
        mapping: function(data) {
            if (data.status && data.status.name) {
                return data.status.name;
            } else {
                return null;
            }
        }
    }
    
+4

json-:

Ext.define('Ext.data.reader.SafeJson', {
extend: 'Ext.data.reader.Json',
alias : 'reader.safe',
/**
 * @private
 * Returns an accessor function for the given property string. Gives support for properties such as the following:
 * 'someProperty'
 * 'some.property'
 * 'some["property"]'
 * This is used by buildExtractors to create optimized extractor functions when casting raw data into model instances.
 */
createAccessor: function() {
    var re = /[\[\.]/;

    return function(expr) {
        if (Ext.isEmpty(expr)) {
            return Ext.emptyFn;
        }
        if (Ext.isFunction(expr)) {
            return expr;
        }
        if (this.useSimpleAccessors !== true) {
            var i = String(expr).search(re);
            if (i >= 0) {

                if (i > 0) {    // Check all property chain for existence. Return null if any level does not exist.
                    var a = [];
                    var l = expr.split('.');
                    var r = '';
                    for (var w in l) {
                        r = r + '.' + l[w];
                        a.push('obj' + r);
                    }
                    var v = "(" + a.join(" && ") + ") ? obj." + expr + " : null";
                    return Ext.functionFactory('obj', 'return (' + v + ')'); 
                } else {
                    return Ext.functionFactory('obj', 'return obj' + expr);
                }
            }
        }
        return function(obj) {
            return obj[expr];
        };
    };
}()
});
0

I changed the example of Glory Nadvorny to work fully for ExtJS 4.1.1.

The new extended class Ext.data.reader.Json is below:

Ext.define('Ext.data.reader.SafeJson', {
    extend: 'Ext.data.reader.Json',
    alias : 'reader.safejson',
    /**
     * @private
     * Returns an accessor function for the given property string. Gives support for properties such as the following:
     * 'someProperty'
     * 'some.property'
     * 'some["property"]'
     * This is used by buildExtractors to create optimized extractor functions when casting raw data into model instances.
     */
    createAccessor: (function() {
        var re = /[\[\.]/;

        return function(expr) {
            if (Ext.isEmpty(expr)) {
                return Ext.emptyFn;
            }
            if (Ext.isFunction(expr)) {
                return expr;
            }
            if (this.useSimpleAccessors !== true) {
                var i = String(expr).search(re);
                if (i >= 0) {
                    if (i > 0) {    // Check all property chain for existence. Return null if any level does not exist.
                        var a = [];
                        var l = expr.split('.');
                        var r = '';
                        for (var w in l) {
                            r = r + '.' + l[w];
                            a.push('obj' + r);
                        }
                        var v = "(" + a.join(" && ") + ") ? obj." + expr + " : null";
                        return Ext.functionFactory('obj', 'return (' + v + ')');
                    } else {
                        return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
                    }
                }
            }
            return function(obj) {
                return obj[expr];
            };
        };
    }()),

        /**
     * @private
     * @method
     * Returns an accessor expression for the passed Field. Gives support for properties such as the following:
     *
     * - 'someProperty'
     * - 'some.property'
     * - 'some["property"]'
     *
     * This is used by buildExtractors to create optimized on extractor function which converts raw data into model instances.
     */
    createFieldAccessExpression: (function() {
        var re = /[\[\.]/;

        return function(field, fieldVarName, dataName) {
            var me     = this,
                hasMap = (field.mapping !== null),
                map    = hasMap ? field.mapping : field.name,
                result,
                operatorSearch;

            if (typeof map === 'function') {
                result = fieldVarName + '.mapping(' + dataName + ', this)';
            } else if (this.useSimpleAccessors === true || ((operatorSearch = String(map).search(re)) < 0)) {
                if (!hasMap || isNaN(map)) {
                    // If we don't provide a mapping, we may have a field name that is numeric
                    map = '"' + map + '"';
                }
                result = dataName + "[" + map + "]";
            } else {                
                if (operatorSearch > 0) {
                    var a = [];
                    var l = map.split('.');
                    var r = '';
                    for (var w in l) {
                        r = r + '.' + l[w];
                        a.push(dataName + r);
                    }
                    result = "("+a.join(" && ")+") ? "+dataName+"."+map+" : null";
                } else {
                    result = dataName + map;
                }
            }            
            return result;
        };
    }())
});

This way you can successfully process nested JSON data with null nodes.

JSON example:

{
    root: [{
        id: 1,
        name: {
            name: "John",
            phone: "123"
        },          
    },
    {
        id: 4,
        name: null,         
    },
    ]
}

A working example with test data can be found here: http://jsfiddle.net/8Ftag/

0
source

All Articles