Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在ExtJS数据模型中忽略空字段?_Javascript_Extjs_Models_Extjs4.1 - Fatal编程技术网

Javascript 如何在ExtJS数据模型中忽略空字段?

Javascript 如何在ExtJS数据模型中忽略空字段?,javascript,extjs,models,extjs4.1,Javascript,Extjs,Models,Extjs4.1,我的问题很长。。。所以,要有耐心:) 我正在使用ExtJS4中的模型,但是我在关联方面遇到了一些问题,所以我创建了一个函数来执行自动模型创建。假设我需要解析以下JSON: { "success": true, "total": 28, "itens": [{ "id":1, "nome":"ACRE", "sigla":"AC", "pais":{ "id":31,

我的问题很长。。。所以,要有耐心:)

我正在使用ExtJS4中的模型,但是我在关联方面遇到了一些问题,所以我创建了一个函数来执行自动模型创建。假设我需要解析以下JSON:

{ 
    "success": true, 
    "total": 28, 
    "itens": [{
        "id":1,
        "nome":"ACRE",
        "sigla":"AC",
        "pais":{
            "id":31,
            "nome":"BRASIL",
            "sigla":"BR"
        }
    },{
        "id":2,
        "nome":"ALAGOAS",
        "sigla":"AL",
        "pais":{
            "id":31,
            "nome":"BRASIL",
            "sigla":"BR"
        }
    }, ...]
}
ITEN代表有一个国家的省份(巴西葡萄牙语为Estados)。我尝试使用ExtJS关联,但我认为它像Java关系一样工作,我错了。对于这个JSON,我有这些Java类和这些Ext模型(这些模型也是使用提供的函数创建的)

Pais.java

@Entity
// named queries here...
public class Pais implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    @NotEmpty
    @Length( max = 100 )
    private String nome;

    @NotNull
    @NotEmpty
    @Column( unique = true )
    @Length( min = 2, max = 4 )
    private String sigla;

    // getters, setters, equals, hashCode and toString here

}
@Entity
// named queries here...
public class Estado implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    @NotEmpty
    @Length( max = 100 )
    private String nome;

    @NotNull
    @NotEmpty
    @Column( unique = true )
    @Length( min = 2, max = 4 )
    private String sigla;

    @NotNull
    @ManyToOne
    private Pais pais;

    // getters, setters, equals, hashCode and toString here

}
Estado.java

@Entity
// named queries here...
public class Pais implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    @NotEmpty
    @Length( max = 100 )
    private String nome;

    @NotNull
    @NotEmpty
    @Column( unique = true )
    @Length( min = 2, max = 4 )
    private String sigla;

    // getters, setters, equals, hashCode and toString here

}
@Entity
// named queries here...
public class Estado implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    @NotEmpty
    @Length( max = 100 )
    private String nome;

    @NotNull
    @NotEmpty
    @Column( unique = true )
    @Length( min = 2, max = 4 )
    private String sigla;

    @NotNull
    @ManyToOne
    private Pais pais;

    // getters, setters, equals, hashCode and toString here

}
创建模型的功能

Ext.ns( "Uteis" );

// other utility functions here...

Uteis.createModel = function( modelData ) {

    var fields = modelData.fields;
    var processedFields = [];
    var normalFields = [];
    var relationFields = [];

    for ( var i in fields ) {

        if ( fields[i].type ) {

            switch ( fields[i].type ) {

                case "auto":
                case "string":
                case "int":
                case "float":
                case "boolean":
                case "date":
                    normalFields.push( fields[i] );
                    break;

                default:

                    var relationField = fields[i];

                    var prefix = relationField.name + ".";
                    var modelInstance = Ext.create( relationField.type );

                    modelInstance.fields.each( function( item, index, length ) {

                        var newField = {};

                        // I used this sintax to make possible create only some fields
                        // if I need in the future.
                        newField["name"] = prefix + item.name;
                        newField["type"] = item.type.type;

                        newField["convert"] = item.convert;
                        newField["dateFormat"] = item.dateFormat;
                        newField["defaultValue"] = item.defaultValue;
                        newField["mapping"] = item.mapping;
                        newField["persist"] = item.persist;
                        newField["sortDir"] = item.sortDir;
                        newField["sortType"] = item.sortType;
                        newField["useNull"] = item.useNull;

                        relationFields.push( newField );

                    });

                    break;

            }

        } else {
            normalFields.push( fields[i] );
        }

    }

    processedFields = normalFields.concat( relationFields );

    // debugging code
    /*console.log( "*** " + modelData.name );
    for ( var i in processedFields ) {
        console.log( processedFields[i] );
    }*/

    Ext.define( modelData.name, {
        extend: "Ext.data.Model",
        fields: processedFields
    });

};
Uteis.createModel({ 
    name: "Modelos.Pais",
    fields: [
        { name: "id",  type: "int" },
        { name: "nome",  type: "string" },
        { name: "sigla",  type: "string" }
    ]
});

Uteis.createModel({ 
    name: "Modelos.Estado",
    fields: [
        { name: "id",  type: "int" },
        { name: "nome",  type: "string" },
        { name: "sigla",  type: "string" },
        { name: "pais", type: "Modelos.Pais" } // <= references the model created above
    ]
});
使用函数创建模型

Ext.ns( "Uteis" );

// other utility functions here...

Uteis.createModel = function( modelData ) {

    var fields = modelData.fields;
    var processedFields = [];
    var normalFields = [];
    var relationFields = [];

    for ( var i in fields ) {

        if ( fields[i].type ) {

            switch ( fields[i].type ) {

                case "auto":
                case "string":
                case "int":
                case "float":
                case "boolean":
                case "date":
                    normalFields.push( fields[i] );
                    break;

                default:

                    var relationField = fields[i];

                    var prefix = relationField.name + ".";
                    var modelInstance = Ext.create( relationField.type );

                    modelInstance.fields.each( function( item, index, length ) {

                        var newField = {};

                        // I used this sintax to make possible create only some fields
                        // if I need in the future.
                        newField["name"] = prefix + item.name;
                        newField["type"] = item.type.type;

                        newField["convert"] = item.convert;
                        newField["dateFormat"] = item.dateFormat;
                        newField["defaultValue"] = item.defaultValue;
                        newField["mapping"] = item.mapping;
                        newField["persist"] = item.persist;
                        newField["sortDir"] = item.sortDir;
                        newField["sortType"] = item.sortType;
                        newField["useNull"] = item.useNull;

                        relationFields.push( newField );

                    });

                    break;

            }

        } else {
            normalFields.push( fields[i] );
        }

    }

    processedFields = normalFields.concat( relationFields );

    // debugging code
    /*console.log( "*** " + modelData.name );
    for ( var i in processedFields ) {
        console.log( processedFields[i] );
    }*/

    Ext.define( modelData.name, {
        extend: "Ext.data.Model",
        fields: processedFields
    });

};
Uteis.createModel({ 
    name: "Modelos.Pais",
    fields: [
        { name: "id",  type: "int" },
        { name: "nome",  type: "string" },
        { name: "sigla",  type: "string" }
    ]
});

Uteis.createModel({ 
    name: "Modelos.Estado",
    fields: [
        { name: "id",  type: "int" },
        { name: "nome",  type: "string" },
        { name: "sigla",  type: "string" },
        { name: "pais", type: "Modelos.Pais" } // <= references the model created above
    ]
});
好的,这些模型(使用我的createModel函数创建)与我的JsonStores配合得很好。到目前为止,Java端的所有映射关联都不是空的,因此,我的存储总是要处理嵌套数据。现在,我必须处理一些可能有空关联的实体,我的问题开始了。需要处理此场景的存储不起作用(存储操作中引发异常,表示字段为空)。我正在使用Gson从我的实体创建JSON。它的默认行为是不序列化空字段,它们在客户端是未定义的,因此我认为如果我序列化空字段(发送空字段),将使Ext实现空字段,而不是尝试处理它。为此,我使用以下代码创建Gson:

Gson gson = new GsonBuilder().serializeNulls().create();
好的,现在正在生成带有空关联的JSON,但是Ext继续抱怨。我尝试使用字段映射和defaultValue配置,但没有成功。为了使事情更简单,让我们以Estados和Paiíses(私人和国家)为例,其中PAI不再是@NotNull。带有空PAI的JSON如下所示:

{ 
    "success": true, 
    "total": 28, 
    "itens": [{
        "id":1,
        "nome":"ACRE",
        "sigla":"AC",
        "pais":null   // <= here
    },{
        "id":2,
        "nome":"ALAGOAS",
        "sigla":"AL",
        "pais":{  // this is not null
            "id":31,
            "nome":"BRASIL",
            "sigla":"BR"
        }
    }, ...]
}
我想知道你是怎么想的。。。谢谢大家!


编辑2:再次您好。我放弃了!:)我将使用我在上面发布的解决方案。我发现它可以改善与模型和网格的关系。我对它们进行了测试,但空字段的问题仍然存在(至少消除了错误)。好的,现在是继续发展的时候了。当应用程序完成后,我将回到这个问题,尝试改进我的解决方案。谢谢大家!

不太确定这是否是问题所在,因为您没有给出确切的错误;但我以前遇到过可选嵌套数据的问题,解决方案是在模型中创建映射函数:

Ext.define( "Modelos.Estado", {
    extend: "Ext.data.Model",
    fields: [
        { name: "id",  type: "int" },
        { name: "nome",  type: "string" },
        { name: "sigla",  type: "string" },
        { name: "pais.id",  type: "int", mapping: function( o ) { return o.pais ? o.pais.id : null; } },
        { name: "pais.nome",  type: "string", mapping: function( o ) { return o.pais ? o.pais.nome : null; } },
        { name: "pais.sigla",  type: "string", mapping: function( o ) { return o.pais ? o.pais.sigla : null; } }
    ]
});

您可以扩展Ext.data.reader.Json,如下所示:

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;
        };
    }())
});
您可以在此处找到测试数据的工作示例:


ExtJS 4.1.1已测试

我不知道模型数据中存在空值的任何特定问题,您是否可以粘贴“Uteis.createModel”函数的输出,以便我们可以看到模型定义在运行后会是什么样子?我认为您需要确保在您的模型上添加具有Ext“associations”属性的嵌套模型数据,但我看不出在用于创建模型的函数中是否存在这些数据。@dougajmcdonald:Hi。我也试过了,我在帖子中解释了。当您尝试获取网格列中的嵌套值时,这些关联不适用于null。函数的输出列在其代码下面的两个代码片段中。在第一个例子中,我展示了函数调用,在第二个例子中,我展示了使用Ext.define()和extend Ext.data.model时将生成的对应模型。我认为这是问题的解决方案