При декларативном создании dojox.grid.DataGrid - как указать вложенные данные в атрибуте поля?
Я создаю dojox.grid.DataGrid в Dojo 1.6 со следующими обозначениями:
<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>
Данные выглядят примерно так:
[{
'id':1,
'contact':{
'name':'Doh',
'firstname':'John',
'tel':'123-123456',
'birthdate':{
'javaClass':'java.sql.Timestamp',
'time':1234567893434}}
}]
Идентификатор отображается в основном, но все остальные отображаются как "...". Я попытался указать форматер, установив базовый объект "контакт" в качестве поля, а затем, например, возвращая имя FIELD.name. Это работает до тех пор, пока отображается правильное значение, но сортировка затем использует базовый объект.
Я думаю, что мог бы быть способ продвинуть это еще дальше, переопределяя сортировку таблицы, но я хотел бы сделать это как можно более простым.
Также я хочу предотвратить появление проблем с производительностью.
Есть идеи?
1 ответ
Я обнаружил, что для определения строки DataGrid существует атрибут, называемый "get". "get" указывает имя функции, которая возвращает значение, отображаемое в столбце DataGrid.
Теоретически это должно решить мою проблему.
Функция get должна быть реализована следующим образом:
Определение сетки:
<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>
Функция обратного вызова (пример):
myGrid.getContactName = function(colIndex,item){
return item.name;
};
Я не могу сказать, в данный момент, является ли эта реализация правильной, так как параметр элемента всегда нулевой в моем приложении.
Это может быть связано с использованием нового API-интерфейса Store (store.Memory) вместо ItemFileReadStore, но мне пока не удалось решить эту головоломку.
Также я не смог протестировать сортировку Gird с этим новым подходом, поэтому я не буду отмечать это решение как решенное.
Обновить
myGrid.getContactName = function(colIndex,record){
if(record)return record.contact.name;
else return null;
};
Как только я предотвратил нулевой случай, все работало нормально.
Однако клиентская сортировка Grid, по-видимому, не доступна через функцию get, а использует поле напрямую. Это предотвращает правильную сортировку вложенных полей.
Обновить
Я наконец-то получил решение своих проблем:
Первая проблема: указание вложенных данных для полей DataGrid было решено уже с использованием функции get для погружения в подструктуру массивов. (это объясняется выше)
Однако сортировка по-прежнему зависит от атрибута поля. Если атрибут поля содержит имя массива, этот столбец будет отсортирован неправильно.
Я должен был изменить несколько классов додзё, чтобы приспособиться к этому. Позже я изложу это в более модульной форме, но вот предварительный результат:
Сначала мне нужно было разрешить определение дополнительного обратного вызова компаратора в определении сетки. Для этого я добавил код в 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);
}
...
}
Затем DataGrid должен передать этот новый параметр запросу, чтобы выполнить сортировку. Это делается в dojox.grid.DataGrid. "с" - это ячейка, которую я модифицировал выше.
getSortProps:function(){
...
return[{attribute:c.field,descending:desc,comparator:c.comparator}];
}
Наконец, мне нужно изменить саму сортировку, которая определена в dojo.store.util.SimpleQueryEngine. SimpleQueryEngine - это механизм по умолчанию для 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;
}
Теперь я могу добавить компараторы в каждый столбец и определить их, где я хочу:
Декларативная установка DataGrid:
...
<td field="myArray" get="getsNameFromArray" comparator="comparesNames">Name</td>
...
Определение Javascript функции сравнения (a и b являются объектами "myArray"):
compareNames = function(a,b){
return a.name > b.name;
}
Javascript-определение функции getter (запись - это целая строка, содержащая объект myArray):
getNamesFromArray= function(idx,record){
return record.myArray.name;
}