Consider the following code:
myexample.html
<polymer-element name="my-example">
<script type="application/dart" src="myexample.dart"></script>
<template>
<style></style>
<div>
<ul>
<template repeat="{{ entry in map.values }}">
<li>{{ entry }}</li>
</template>
</ul>
<button on-click="{{add}}">Add</button>
</div>
</template>
</polymer-element>
myexample.dart
@CustomTag('my-example')
class MyExample extends PolymerElement {
@observable Map<int, String> map = toObservable({});
int i = 0;
MyExample.created() : super.created();
void add() {
map[i++] = i.toString();
}
}
The map is filled on every click of the "Add" button, but the map-entries aren't shown in myexample.html. So: How to use (and to iterate) an observable Map properly, such that the list in the html-file is updated automatically?
This is a bug. I just filed it:
https://code.google.com/p/dart/issues/detail?id=15407
Please star the issue so that you can be notified when the bug is fixed.
Polymer >= 1.0.0-rc.x
Observable isn't used in the new Polymer anymore.
The best I could make work in the new Polymer is
dart
@HtmlImport('app_element.html')
library dom_repeat_map.web.app_element;
import 'package:web_components/web_components.dart' show HtmlImport;
import 'package:polymer/polymer.dart';
@PolymerRegister('app-element')
class AppElement extends PolymerElement {
AppElement.created() : super.created();
Map _data = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6};
@property
Iterable get dataKeys => _data.keys;
@reflectable
int dataValue(String key) => _data[key];
}
See also What is the alternative to maps in polymer Dart 1.0?
html
<dom-module id='app-element'>
<template>
<template is="dom-repeat" items="{{dataKeys}}" as="key">
<div><span>[[key]]</span>-<span>[[dataValue(key)]]</span></div>
</template>
</template>
</dom-module>
Polymer.dart <= 0.16.x only
The template repeat code is fine. If you initialize the map like
@observable Map<int, String> map = toObservable({10: '10', 11: '11'});
you will see the values on the page. I have to investigate further to see why it is not updated when you add new entries.
What you could use until this is solved:
library x;
import 'dart:async';
import 'package:polymer/polymer.dart';
@CustomTag('my-example')
class MyExample extends PolymerElement {
@observable ObservableMap map = toObservable(<int, String>{});
int i = 0;
MyExample.created() : super.created() {
map.changes.listen((e) => mapChanged(null));
}
@observable List<int> get keys => toObservable(map.keys.toList());
@observable List<String> get values => toObservable(map.values.toList());
void mapChanged(old) {
print('mapChanged');
this.notifyPropertyChange(#keys, 1, 0); // there are better values than 1 and 0 I guess, but it works
this.notifyPropertyChange(#values, 1, 0);
}
// void attached() {
// super.attached();
// new Timer.periodic(new Duration(milliseconds: 2000), (e) => add());
// }
void add() {
map[i++] = i.toString();
print(map.toString());
}
}
The bug is fixed in bleeding edge:
https://codereview.chromium.org/213743012/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With