I have a dom-repeat
template that generates table rows, where one of the row cells contains a button, that I want to get disabled when the row value is of certain value. So my component has this code, which uses a computed binding to set the value of the button's disabled
property:
<template is="dom-repeat" items="{{list}}" as="ticket">
<tr class$="{{ticket.status}}">
<td class="actions">
<paper-icon-button icon="add" on-tap="incTickets"
disabled="{{noAvailableTickets(ticket)}}">
</paper-icon-button>
</td>
<td>[[ticket.amount]]</td>
<td>[[ticket.event.title]]</td>
</tr>
</template>
And in my code I have this method:
noAvailableTickets : function(ticket) {
return ticket.event.available_tickets <= 0;
}
I can see that the computed binding method is called when the list is first created, once for each item.
Then when I update items, like this:
this.set('list.' + ind + '.amount', newamount);
The computed binding is not recalcuated, and the method is not called again, even though I can see the value actually change in the ticket.amount
display in the template.
The Polymer Data Binding entry in the developer's guide has this to say about computed bindings:
the [...] property is bound to the return value of
computeFullName
, which is recalculated whenever first or last changes. [first
andlast
are the declared arguments forcomputeFullName
]
So under the assumption that the computed binding is not aware of the correlation between the object value, its amount
property and how other logic uses this to update the available_tickets
property, I've tried to add a notifyPath
command with the full updated object, like this:
this.notifyPath('list.' + displayId, ticket);
But that didn't seem to have any effect. What am I missing?
I suspect notifyPath
isn't triggering an update in your case because of its dirty check. That is, list[0]
and ticket
refer to the same instance (despite the fact that the instance's property has changed), so it's not considered "dirty".
My jsbin experiment demonstrates that setting list[0]
to a modified clone indeed triggers an update.
attached: function() {
setTimeout(function() {
var copy = this.list[0].clone();
copy.amount = 'FREE';
this.set('list.0', copy);
}.bind(this), 1000);
}
But that's probably not the best way to accomplish this.
According to Polymer docs, to trigger the computed binding whenever a ticket
subproperty changes, you would use ticket.*
in your binding:
<paper-icon-button disabled="{{noAvailableTickets(ticket.*)}}">
Polymer({
...
noAvailableTickets: function(change) {
var ticket = change.base;
return ticket.event.available_tickets <= 0;
}
});
Here's a jsbin.