Updating a Map doesn't trigger binding updates


I’m using a Map to store some metadata. The elements get updated on user interaction. My template displays some of this metadata. However updating the data won’t be reflected in the template.


    <a click.trigger="update()">Update</a>


class SampleCustomElement {
    myMap: Map<string, string> = new Map();
    update() {
        this.myMap.set('foo', 'bar');

I found out that ModifyMapObserver would patch the Map to inject observable behaviour but somehow it doesn’t work.

Did anyone have tried something like that already?



myMap.get('foo') is a function call and won’t be observed for changes.

If you don’t mind dirty checking, then you can use a get-property in your view-model

get foo() {
  return myMap.get('foo');


I’ve found it better to just change my pattern to immutable collections in my components. This is much cleaner and the binding just works. Try creating a new map object in the update() method.

If the map is bound (input) to your element, then the update method in SampleCustomElement should call a method (output) in the parent component to set the item. The parent component would own all updates to map and a new map is created whenever needed.

Over the past year, I’ve realized that this pattern of inputs and outputs makes for clean code and reliable binding.


Thanks for your responses! I’m going with @swalters suggestion and using immutable collections. This works flawlessly.


I actually just opened up an issue about this here: https://github.com/aurelia/binding/issues/642

Turns out what I did to work around it was to iterate over the map and select the item that matches the right key.

<div repeat.for="key, value of map" if.bind="key === 'foo'></div>

I think we all agree this isn’t good. However, I did this way back in the alpha days of Aurelia and never had the problem again. I think it would be great to add this to the binding engine, but it’s just a super low priority for most developers at the moment.


@davismj to observe a Map, does aurelia just have to intercept calls to set?


It already does: https://github.com/aurelia/binding/blob/master/src/map-observation.js.

The problem is that it handles these changes the same way it handles array mutations. If you push to an array, the first n items don’t have their bindings refreshed. Only iterable bindings (repeat.for) do. This is why the above strategy works.

<div repeat.for="key, value of map" if.bind="key === 'foo'></div>


@davismj using 2 template controller on the same elements may not work well on IE


It’s time to make Map great again, then.