I'm creating a dojox.grid.DataGrid in dojo 1.6 with the following notation:
<table dojoType="dojox.grid.DataGrid">
<thead>
<tr>
<th field="id">ID</th>
<th field="contact.name">Name</th>
<th field="contact.tel">Telephone</th>
<th field="contact.birthdate.time">Birthday</th>
</tr>
</thead>
</table>
The Data looks something like this:
[{
'id':1,
'contact':{
'name':'Doh',
'firstname':'John',
'tel':'123-123456',
'birthdate':{
'javaClass':'java.sql.Timestamp',
'time':1234567893434}}
}]
ID is rendered corectly, but all the others render as "...".
I have tried to specify a formatter, setting the base Object "contact" as
the FIELD and then returning FIELD.name for example.
This works in so far that the correct Value is displayed, but the Sorting then
uses the base object.
I think there might be a way to push this even further, overriding the sorting
of the table, but I would like to keep this as simple as possible.
Also I wish to prevent performance issues from popping up.
Any Ideas?
I have found out that there is an attribute for the DataGrid row definition called "get".
"get" specifies the name of a function that returnes the value to be displayed in the DataGrid column.
Theoretically this should solve my Problem.
The get-function is to be implemented in the following way:
Grid Definition:
<table dojoType="dojox.grid.DataGrid">
<thead>
<tr>
<th field="id">ID</th>
<th field="contact" get="myGrid.getContactName">Name</th>
<th field="contact" get="myGrid.getContactTel">Telephone</th>
<th field="contact" get="myGrid.getContactBirthdateTime">Birthday</th>
</tr>
</thead>
</table>
Callback Function (example):
myGrid.getContactName = function(colIndex,item){
return item.name;
};
I can not tell at the Moment if this implementation is correct, since
the item parameter is always null in my application.
This could be due to the use of the new Store API (store.Memory) instead of the ItemFileReadStore, but I have not been successfull in solving this puzzle yet.
Also I was not able to test Gird sorting with this new approach, so I will not flag
this sollution as resolved yet.
update
myGrid.getContactName = function(colIndex,record){
if(record)return record.contact.name;
else return null;
};
Once I averted the null case it worked fine this way.
However client sort of the Grid doesn't seem to access through the get function but uses the field directly. This prevents correct sorting on nested fields.
update
I finally got a sollution for my problems:
The first problem : specifying nested data for the DataGrid fields was solved allready using the get-function to dive into the arrays substructure. (that is explained above)
Sorting however is still dependent on the field attribute.
If the field attribute contains the name of an array this column will not sort correctly.
I had to modify a few dojo classes to accomodate for that. I will later put this in a more modular form, but here is the raw result for now:
First I needed to allow the definition of an addtional comparator callback in the Grid Definition.
For that I have added some code to the dojox.grid.cells._base
dgc._Base.markupFactory = function(node, cellDef){
var d = dojo;
...
var comparator = d.trim(d.attr(node,"comparator")||"");
if(comparator){
cellDef.comparator = dojo.getObject(comparator);
}
...
}
Next the DataGrid needs to give this new parameter to the query to do the sorting.
This is done in the dojox.grid.DataGrid. "c" is the Cell I modified above.
getSortProps:function(){
...
return[{attribute:c.field,descending:desc,comparator:c.comparator}];
}
Finally I need to change the sorting itself which is defined in dojo.store.util.SimpleQueryEngine.
SimpleQueryEngine is the default Engine for the MemoryStore (dojo.store.Memory).
function execute(array){
// execute the whole query, first we filter
var results = dojo.filter(array, query);
// next we sort
if(options && options.sort){
results.sort(function(a, b){
for(var sort, i=0; sort = options.sort[i]; i++){
var aValue = a[sort.attribute];
var bValue = b[sort.attribute];
if (aValue != bValue) {
// changed Part start
if(options.sort[i].comparator){
return !!sort.descending == options.sort[i].comparator(aValue,bValue) ? -1 : 1;
}
else{
return !!sort.descending == aValue > bValue ? -1 : 1;
}
// changed Part end
}
}
return 0;
});
}
...
return results;
}
Now I can add comparators to each column and define them where I want to:
Declarative DataGrid Setup:
...
<td field="myArray" get="getsNameFromArray" comparator="comparesNames">Name</td>
...
Javascript definition of the comparator function (a and b are "myArray" objects):
compareNames = function(a,b){
return a.name > b.name;
}
Javascript definition of the getter function (record is the whole row and contains the "myArray" object):
getNamesFromArray= function(idx,record){
return record.myArray.name;
}