Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use and to iterate an observable map in Dart Polymer?

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?

like image 842
melmac Avatar asked Dec 02 '13 17:12

melmac


3 Answers

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.

like image 190
Shailen Tuli Avatar answered Nov 01 '22 16:11

Shailen Tuli


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());
  }
}
like image 41
Günter Zöchbauer Avatar answered Nov 01 '22 16:11

Günter Zöchbauer


The bug is fixed in bleeding edge:

https://codereview.chromium.org/213743012/

like image 25
bey Avatar answered Nov 01 '22 16:11

bey