mcosta
10 Jul 2009, 2:11 AM
Hello, I have searched the forums and seems many people has hit this problem, but not with GXT. Aplying a XTemplate when you have a ModelData's property and it is null results in a undefined reference. That is counter intuitive in the eyes of a Java developer who sees a clear contract break in the interface. I have a property, just happens it's null, and the template has to deal with it gracefully.
But the "offending" code it is not in XTemplate, it is in the conversión from ModelData to JsObject in com.extjs.gxt.ui.client.util.Util
public static JavaScriptObject getJsObject(ModelData model, int maxDepth) {
JsObject jsObj = new JsObject();
for (String key : model.getPropertyNames()) {
Object value = model.get(key);
if (value == null) continue;
if (maxDepth > 0) {
if (value instanceof Collection) {
jsObj.set(key, processCollection((Collection) value, maxDepth).getJsObject());
} else if (value instanceof Object[]) {
jsObj.set(key, processArray((Object[]) value, maxDepth).getJsObject());
} else if (value instanceof ModelData) {
jsObj.set(key, getJsObject((ModelData) value, maxDepth - 1));
} else {
jsObj.set(key, value);
}
} else {
jsObj.set(key, value);
}
}
return jsObj.getJsObject();
}
See? if (value==null) then forget about it, bad luck dude. My beloved properties are lost. Using ModelProccesor in ListViews mitigates this, but these ModelData are bussines objects and the semantics depends of null values. So we have to clone the objects, with the performance penalty. And do not forget to setup the listviews.
But there's salvation for out properties. Changing this code to
public static JavaScriptObject getJsObject(ModelData model, int maxDepth) {
JsObject jsObj = new JsObject();
for (String key : model.getPropertyNames()) {
Object value = model.get(key);
if (maxDepth > 0) {
if (value == null) {
jsObj.set(key, "");
} else if (value instanceof Collection) {
jsObj.set(key, processCollection((Collection) value, maxDepth).getJsObject());
} else if (value instanceof Object[]) {
jsObj.set(key, processArray((Object[]) value, maxDepth).getJsObject());
} else if (value instanceof ModelData) {
jsObj.set(key, getJsObject((ModelData) value, maxDepth - 1));
} else {
jsObj.set(key, value);
}
} else {
jsObj.set(key, value);
}
}
return jsObj.getJsObject();
}
Should render the templates ok. I have inspected other places where this method is used and everything looks fine. But I can't build GXT to test the change
But the "offending" code it is not in XTemplate, it is in the conversión from ModelData to JsObject in com.extjs.gxt.ui.client.util.Util
public static JavaScriptObject getJsObject(ModelData model, int maxDepth) {
JsObject jsObj = new JsObject();
for (String key : model.getPropertyNames()) {
Object value = model.get(key);
if (value == null) continue;
if (maxDepth > 0) {
if (value instanceof Collection) {
jsObj.set(key, processCollection((Collection) value, maxDepth).getJsObject());
} else if (value instanceof Object[]) {
jsObj.set(key, processArray((Object[]) value, maxDepth).getJsObject());
} else if (value instanceof ModelData) {
jsObj.set(key, getJsObject((ModelData) value, maxDepth - 1));
} else {
jsObj.set(key, value);
}
} else {
jsObj.set(key, value);
}
}
return jsObj.getJsObject();
}
See? if (value==null) then forget about it, bad luck dude. My beloved properties are lost. Using ModelProccesor in ListViews mitigates this, but these ModelData are bussines objects and the semantics depends of null values. So we have to clone the objects, with the performance penalty. And do not forget to setup the listviews.
But there's salvation for out properties. Changing this code to
public static JavaScriptObject getJsObject(ModelData model, int maxDepth) {
JsObject jsObj = new JsObject();
for (String key : model.getPropertyNames()) {
Object value = model.get(key);
if (maxDepth > 0) {
if (value == null) {
jsObj.set(key, "");
} else if (value instanceof Collection) {
jsObj.set(key, processCollection((Collection) value, maxDepth).getJsObject());
} else if (value instanceof Object[]) {
jsObj.set(key, processArray((Object[]) value, maxDepth).getJsObject());
} else if (value instanceof ModelData) {
jsObj.set(key, getJsObject((ModelData) value, maxDepth - 1));
} else {
jsObj.set(key, value);
}
} else {
jsObj.set(key, value);
}
}
return jsObj.getJsObject();
}
Should render the templates ok. I have inspected other places where this method is used and everything looks fine. But I can't build GXT to test the change