Карты в Списках в Картах
После долгих проб и ошибок я не могу понять, что делать со встроенными списками и картами в Dart, а также, как к ним можно обращаться через привязку данных Polymer. Цель состоит в том, чтобы прочитать файл JSON и создать таблицу HTML, которую можно фильтровать и сортировать. (Я просто жестко закодировал данные карты ниже для ясности.)
Я могу построить HTML-таблицу в своем элементе Polymer (см. BuildTable), если карта выглядит как testMap3, представленный в коде Dart ниже, и хорошо отрисовывается с помощью:
HTML:
<p><b>The data from testMap3 after building table in Dart file:</b>/p>
<table class="bordered" id="dataTable"></table>
Тем не менее, я не могу понять, как сделать это с помощью привязки данных Polymer. Сейчас я просто сбрасываю пары kv, чтобы увидеть объекты:
HTML:
<p><b>The data from testMap3 via Polymer binding:</b></p>
<template repeat="{{key in testMap.keys}}">
<p>{{key}} : {{testMap[key]}}</p>
</template>
Как я могу использовать привязку данных для создания таблицы, которая будет соответствовать результату первого примера выше? И чтобы сделать вещи более сложными, как я могу сделать это, используя testMap2 вместо этого?
Dart:
Рендеринг testMap3 работает нормально при вызове buildTable:
Map testMap3 = toObservable({
'columns' : ["First Name", "Attending", "Phone"],
'rows' : [{'First Name' : "Alice",
'Attending' : "Yes",
'Phone' : "555-1212"},
{'First Name' : "Bob",
'Attending' : "Yes",
'Phone' : "555-2323"}
]
});
Итерация по testMap2 была проблематичной, учитывая, что дополнительное встроенное значение "Телефон" представляет собой список, содержащий другую карту:
Map testMap2 = toObservable({
'columns' : ["First Name", "Attending", "Phone"],
'rows' : [{'First Name' : "Alice",
'Attending' : "Yes",
'Phone' : [{'Home' : "555-1234",
'Work' : "555-4321",
'Mobile' : "555-1212"}]},
{'First Name' : "Bob",
'Attending' : "Yes",
'Phone' : [{'Home' : "555-2345",
'Work' : "555-5432",
'Mobile' : "555-2323"}]}
]
});
Следующий код прекрасно работает для testMap3, но все, что я пробовал, позволяет мне просматривать данные телефона, если я использую testMap2. Любые идеи о том, как я могу это сделать?
buildTable() {
TableElement table = this.shadowRoot.querySelector("#dataTable");
table.children.clear();
TableSectionElement tBody = table.createTBody();
TableSectionElement tHead = table.createTHead();
TableRowElement trh = tHead.addRow();
for (var column in testMap3["columns"]) {
var cell = new Element.tag('th');
cell.text = column;
trh.append(cell);
}
for (var row in testMap3["rows"]) {
TableRowElement tr = tBody.addRow();
for (var column in testMap3["columns"]) {
tr.addCell().text = row[column];
}
}
}
Наконец, одна из конечных целей состоит в том, чтобы отфильтровать все столбцы в отображаемой таблице, используя подход, подобный следующему... это выполнимо? Я не могу найти примеры использования Карт или даже списков в списках.
HTML:
<template repeat="{{city in listOfCities | filter(searchParameter)}}">
<li>{{city}}</li>
</template>
Dart:
@observable List listOfCities = ["Chicago", "New York", "Los Angeles", "Dallas", "Denver"];
filter(term) => (listOfCities) => term.isEmpty ? listOfCities : listOfCities.where((item) => item.toLowerCase().contains(searchParameter.toLowerCase())).toList();
Любое руководство очень ценится, так как я бился головой более недели и почти готов сдаться.
Спасибо!
2 ответа
Следующая привязка данных Polymer будет работать для testMap3:
<table>
<thead>
<tr>
<td template repeat="{{column in testMap3['columns']}}">{{column}}</td>
</tr>
</thead>
<tbody>
<tr template repeat="{{row in testMap3['rows']}}">
<td template repeat="{{data in row.keys}}">{{row[data]}}</td>
</tr>
</tbody>
</table>
Фильтрация по строкам таблицы может быть выполнена с помощью следующего метода:
filter(term) => (rows) => term.isEmpty
? rows
: rows.where((row) => row.values.any((val) => val.toLowerCase().contains(term)));
Он просматривает все данные строки и сопоставляет каждый столбец с поисковым термином.
Тогда тело будет выглядеть так:
<tbody>
<tr template repeat="{{row in testMap3['rows'] | filter(search)}}">
<td template repeat="{{data in row.keys}}">{{row[data]}}</td>
</tr>
</tbody>
И это предполагает, что у вас есть ввод текста, который подключается к строковому значению с именем search
,
Вы можете попробовать это
<table>
<thead>
<tr>
<th template repeat="{{item in testMap3['columns']}}">{{item}}</th>
</tr>
</thead>
<tbody>
<tr template repeat="{{row in testMap3['rows']}}">
<td template repeat="{{key in testMap3['columns']}}">{{row[key]}}</td>
</tr>
</tbody>
</table>
<tr template repeat="...">
такой же как
<template repeat="...">
но вы не можете использовать в таблице, поэтому вы вынуждены использовать
<tr template repeat="...">
Извините, я не знаю, почему это нужно сделать таким образом, вам придется провести собственное исследование по этому вопросу. Он выдаст ошибку, если вы попытаетесь сделать это с помощью
<table>
<template repeat="...">
<tr><td></td></tr>
</template>
</table>
так как <шаблон> не допускается внутри элементов таблицы.
Что касается фильтрации
ты мог бы сделать это
@observable String search = '';
filter(search) => (List row) =>
row.where((item) => item['Phone'].contains(search));
для фильтрации по телефону
или фильтр для любого значения, которое соответствует строке поиска
filter(String search) => (List row) =>
row.where((Map item) => item.values.any((val) => val.toLowerCase().contains(search.toLowerCase())));
который похож на другой ответ от @pixel-elephant