For this object:
obj = {
a:'a value',
b:'b value'
}
I need to call a function whenever a
's or b
's value is changed.
I saw Observe changes for an object in Polymer JS, but that solution is not working for me.
I tried unsuccessfully to add an observer like this:
observers: [
'abc(obj.*)' //abc is function which need to be called
]
and:
observe: {
'obj.a': 'abc' // here I'm observing a's attribute
},
Plunker: http://plnkr.co/edit/BvX25wJHJh7i2aeyVBks?p=preview
In your Plunker, the observer is not called after the changes to obj.a
in your ready()
callback because the subproperty was directly assigned, which does not automatically fire a change-event for observers (or data bindings) to see. Here's the corrected plunker.
Polymer docs describe how to observe subproperty changes:
In order for Polymer to properly detect the sub-property change, the sub-property must be updated in one of the following two ways:
- Via a property binding.
- By calling
set
.
There's also a third way: by calling notifyPath
.
After making changes to this.obj.a
, you can notify observers and update bindings by calling this.notifyPath('obj.a', this.obj.a)
:
this.obj.a = 100;
this.obj.a++;
this.notifyPath('obj.a', this.obj.a);
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
properties: {
obj: {
type: Object,
value: () => ({a: 1, b: 2})
}
},
observers: [
'_objChanged(obj.a, obj.b)'
],
_objChanged: function(a, b) {
console.log('a', a, 'b', b);
},
_doNotifyPath: function() {
this.obj.a++;
this.obj.b++;
this.notifyPath('obj.a', this.obj.a);
this.notifyPath('obj.b', this.obj.b);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.11.3/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<div>obj.a = [[obj.a]]</div>
<div>obj.b = [[obj.b]]</div>
<button on-tap="_doNotifyPath">Notify Path</button>
</template>
</dom-module>
</body>
Alternatively, you could combine the setting and notification with this.set('obj.a', 'new value')
:
this.set('obj.a', this.obj.a + 1);
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
properties: {
obj: {
type: Object,
value: () => ({a: 1, b: 2})
}
},
observers: [
'_objChanged(obj.a, obj.b)'
],
_objChanged: function(a, b) {
console.log('a', a, 'b', b);
},
_doSet: function() {
this.set('obj.a', this.obj.a + 1);
this.set('obj.b', this.obj.b + 1);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.11.3/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<div>obj.a = [[obj.a]]</div>
<div>obj.b = [[obj.b]]</div>
<button on-tap="_doSet">Set</button>
</template>
</dom-module>
</body>