After much trial and error, I am at a loss as to how to deal with embedded lists and maps in Dart and furthermore, how they can be accessed via Polymer data binding. The objective is to read a JSON file and build an HTML table that can be filtered and sorted. (I just hard coded map data below for clarity.)
I can build an HTML table within my Polymer element (see buildTable) as long as the Map looks like testMap3 seen in the Dart code below and it renders fine with:
HTML:
<p><b>The data from testMap3 after building table in Dart file:</b>/p>
<table class="bordered" id="dataTable"></table>
However, I can't seem to figure out how to do this via Polymer data binding. Right now I am just dumping the k-v pairs, just so that I can see the objects:
HTML:
<p><b>The data from testMap3 via Polymer binding:</b></p>
<template repeat="{{key in testMap.keys}}">
<p>{{key}} : {{testMap[key]}}</p>
</template>
How can I use data binding to create a table that would match the result of the first example above? And to make things more difficult, how can I do so using testMap2 instead?
Dart:
Rendering testMap3 works fine when calling 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"}
]
});
Iterating through testMap2 has been problematic given the additional embedded 'Phone' value is a list containing another map:
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"}]}
]
});
The following code works fine for testMap3 but nothing I have tried lets me loop through the phone data if I use testMap2. Any ideas on how I can do this?
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];
}
}
}
Finally, one of the ultimate goals is to filter all the columns in the rendered table taking an approach similar to the following...is this doable? I can't seem to find examples using Maps or even Lists within Lists.
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();
Any guidance is greatly appreciated as I have been banging my head for over a week and am just about ready to give up.
Thanks!
The following Polymer databinding will work for 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>
Filtering on table rows could be accomplished with the following method:
filter(term) => (rows) => term.isEmpty
? rows
: rows.where((row) => row.values.any((val) => val.toLowerCase().contains(term)));
It looks through the entire row data and matches each column against the search term.
The tbody would then look like this:
<tbody>
<tr template repeat="{{row in testMap3['rows'] | filter(search)}}">
<td template repeat="{{data in row.keys}}">{{row[data]}}</td>
</tr>
</tbody>
And it assumes you have a text input that hooks up to a String value named search
.