PDA

View Full Version : How to ignore null fields in ExtJS data models?



davidbuzatto
12 Jul 2012, 12:54 PM
Hello!
My question is very long... So, be patient :)

I'm working with models in ExtJS 4, but I'm having some problems with the associations, so I created a function to perform the automatic model creation for me. Lets suppose I need to parse the following 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"
}
}, ...]
}

The itens represent Provinces (Estados in Brazilian portuguese) with have a Country (País in brazilian portuguese). I tried to use ExtJS associations, but I thought that it works like Java relationships and I think I was wrong... Well, for this JSON I have these Java classes and these Ext Models (the models are created using the function provided too).

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

}

Estado.java


@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

}

Function to create the models


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
});

};

Using function to create the models


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
]
});

The code above is correspondent to this. I created the function to automatize the creation of nested data fields (because the problem of the associations that I said).


Ext.define( "Modelos.Pais", {
extend: "Ext.data.Model",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" }
]
});

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" },
{ name: "pais.nome", type: "string" },
{ name: "pais.sigla", type: "string" }
]
});

Ok, these models (created using my createModel function) work very well with my JsonStores. Until now, all of the mapping associations in the Java side were not null, so, my stores always have nested data to process. Now, I have to process some entities that can have null associations and my problems began. The store that needs to deal with this scenario not works (an exception is being thrown in the store operation, saying that the fields are null). I'm using Gson to create JSON from my entities. Its default behaviour is to not serialize null fields, them they will be undefined in the client side, so I though that if I serialize the null fields (sending a null) would make Ext to realize the null field and not try to process it. To do this I used this code to create the Gson:


Gson gson = new GsonBuilder().serializeNulls().create();

Ok, now the JSON with null associations is being generated, but the Ext continues to complain. I tried to use the field mapping and defaultValue configs with no success. To make the things simpler, lets use the example of Estados and Países (Privinces and Countries) where Pais is not @NotNull anymore. The JSON with a null pais would be like:


{
"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"
}
}, ...]
}

With this code, the pais.id, pais.nome and pais.sigla fields would not be available, since the pais property is null. So, my question is: How to make the store ignore some fields when they are null or undefined? I already tried to search for a solution with no success... Thank you very much!

mayur_satasiya
26 Jul 2012, 10:44 PM
Hello!
My question is very long... So, be patient :)

I'm working with models in ExtJS 4, but I'm having some problems with the associations, so I created a function to perform the automatic model creation for me. Lets suppose I need to parse the following 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"
}
}, ...]
}

The itens represent Provinces (Estados in Brazilian portuguese) with have a Country (País in brazilian portuguese). I tried to use ExtJS associations, but I thought that it works like Java relationships and I think I was wrong... Well, for this JSON I have these Java classes and these Ext Models (the models are created using the function provided too).

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

}

Estado.java


@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

}

Function to create the models


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
});

};

Using function to create the models


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
]
});

The code above is correspondent to this. I created the function to automatize the creation of nested data fields (because the problem of the associations that I said).


Ext.define( "Modelos.Pais", {
extend: "Ext.data.Model",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" }
]
});

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" },
{ name: "pais.nome", type: "string" },
{ name: "pais.sigla", type: "string" }
]
});

Ok, these models (created using my createModel function) work very well with my JsonStores. Until now, all of the mapping associations in the Java side were not null, so, my stores always have nested data to process. Now, I have to process some entities that can have null associations and my problems began. The store that needs to deal with this scenario not works (an exception is being thrown in the store operation, saying that the fields are null). I'm using Gson to create JSON from my entities. Its default behaviour is to not serialize null fields, them they will be undefined in the client side, so I though that if I serialize the null fields (sending a null) would make Ext to realize the null field and not try to process it. To do this I used this code to create the Gson:


Gson gson = new GsonBuilder().serializeNulls().create();

Ok, now the JSON with null associations is being generated, but the Ext continues to complain. I tried to use the field mapping and defaultValue configs with no success. To make the things simpler, lets use the example of Estados and Países (Privinces and Countries) where Pais is not @NotNull anymore. The JSON with a null pais would be like:


{
"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"
}
}, ...]
}

With this code, the pais.id, pais.nome and pais.sigla fields would not be available, since the pais property is null. So, my question is: How to make the store ignore some fields when they are null or undefined? I already tried to search for a solution with no success... Thank you very much!

Hi, Try to use
registerTypeAdapter it may help you
Thanks
Mayur

davidbuzatto
27 Jul 2012, 3:26 AM
Hi Myaur.

First of all, thank you very much for your reply. I will try what you said, but I already solved my problem in server side. I explained my solution here: http://stackoverflow.com/questions/11460270/how-to-ignore-null-fields-in-extjs-data-models

See ya!