Skip to content

Commit

Permalink
Fix negation when a negated binding is changed
Browse files Browse the repository at this point in the history
  • Loading branch information
TimvdLippe committed Feb 5, 2016
1 parent 9968266 commit 21383a3
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 110 deletions.
17 changes: 11 additions & 6 deletions src/lib/bind/accessors.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
_notifyChange: function(source, event, value) {
value = value === undefined ? this[source] : value;
event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed';
this.fire(event, {value: value},
this.fire(event, {value: value},
{bubbles: false, cancelable: false, _useCache: true});
},

Expand Down Expand Up @@ -189,12 +189,12 @@
return name[0].toUpperCase() + name.substring(1);
},

_addAnnotatedListener: function(model, index, property, path, event) {
_addAnnotatedListener: function(model, index, property, path, event, negated) {
if (!model._bindListeners) {
model._bindListeners = [];
}
var fn = this._notedListenerFactory(property, path,
this._isStructured(path));
this._isStructured(path), negated);
var eventName = event ||
(Polymer.CaseMap.camelToDashCase(property) + '-changed');
model._bindListeners.push({
Expand All @@ -214,17 +214,22 @@
return e.path && e.path[0] !== target;
},

_notedListenerFactory: function(property, path, isStructured) {
_notedListenerFactory: function(property, path, isStructured, negated) {
return function(target, value, targetPath) {
if (targetPath) {
this._notifyPath(this._fixPath(path, property, targetPath), value);
} else {
// TODO(sorvell): even though we have a `value` argument, we *must*
// lookup the current value of the property. Multiple listeners and
// queued events during configuration can theoretically lead to
// divergence of the passed value from the current value, but we
// queued events during configuration can theoretically lead to
// divergence of the passed value from the current value, but we
// really need to track down a specific case where this happens.
value = target[property];

if (negated) {
value = !value;
}

if (!isStructured) {
this[path] = value;
} else {
Expand Down
3 changes: 1 addition & 2 deletions src/lib/bind/effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
effect.kind != 'attribute' &&
effect.kind != 'text' &&
!effect.isCompound &&
effect.parts[0].mode === '{' &&
!effect.parts[0].negate;
effect.parts[0].mode === '{';
},

_annotationEffect: function(source, value, effect) {
Expand Down
2 changes: 1 addition & 1 deletion src/standard/effectBuilder.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
if (Polymer.Bind._shouldAddListener(note)) {
// <node>.on.<dash-case-property>-changed: <path> = e.detail.value
Polymer.Bind._addAnnotatedListener(this, index,
note.name, note.parts[0].value, note.parts[0].event);
note.name, note.parts[0].value, note.parts[0].event, note.parts[0].negate);
}
for (var i=0; i<note.parts.length; i++) {
var part = note.parts[i];
Expand Down
6 changes: 6 additions & 0 deletions test/unit/bind-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@
notifyingvalue="{{computedValue}}"
computedvalue="{{value}}">
</x-basic>
<x-basic id="basic4"
notifyingvalue="{{!negatedValue}}">
</x-basic>
</template>
<script>
Polymer({
Expand All @@ -313,6 +316,9 @@
},
computedValue: {
computed: 'computeComputedValue(a, b)'
},
negatedValue: {
value: false
}
},
created: function() {
Expand Down
7 changes: 7 additions & 0 deletions test/unit/bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,13 @@
assert.equal(listener.getCalls()[0].args[0].detail.value, 678);
});

test('negated binding update negates value for parent', function() {
assert.equal(el.negatedValue, false);
assert.equal(el.$.basic4.notifyingvalue, true);
el.$.basic4.notifyingvalue = false;
assert.equal(el.negatedValue, true);
});

});

suite('1-way binding effects between elements', function() {
Expand Down
1 change: 0 additions & 1 deletion test/unit/notify-path-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<template>
<x-basic id="basic1" notifying-value="{{obj.value}}" attrvalue$="{{obj.value}}" othervalue="{{obj.value2}}"></x-basic>
<x-basic id="basic2" notifying-value="{{obj.value}}" attrvalue$="{{obj.value}}"></x-basic>
<x-basic id="basic3" notifying-value="{{!obj.value}}" attrvalue$="{{!obj.value}}"></x-basic>
</template>
<script>
Polymer({
Expand Down
100 changes: 0 additions & 100 deletions test/unit/notify-path.html
Original file line number Diff line number Diff line change
Expand Up @@ -234,106 +234,6 @@
verifyNonNestedObserversOutput();
});

test('negation', function() {
// Setup
var nested = {
obj: {
value: false
}
};
// Do the thing
el.nested = nested;
// Verify
assert.equal(el.$.basic.notifyingValue, false);
assert.equal(el.$.compose.$.basic1.notifyingValue, false);
assert.equal(el.$.compose.$.basic2.notifyingValue, false);
assert.equal(el.$.compose.$.basic3.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic3.notifyingValue, true);
assert.equal(el.$.basic.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), true);

// Do another thing
el.$.basic.notifyingValue = true;
// Verify
assert.equal(el.$.basic.notifyingValue, true);
assert.equal(el.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.compose.$.basic3.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic3.notifyingValue, false);
assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);

// Do another thing
el.$.forward.$.compose.$.basic1.notifyingValue = false;
// Verify
assert.equal(el.$.basic.notifyingValue, false);
assert.equal(el.$.compose.$.basic1.notifyingValue, false);
assert.equal(el.$.compose.$.basic2.notifyingValue, false);
assert.equal(el.$.compose.$.basic3.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic3.notifyingValue, true);
assert.equal(el.$.basic.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), false);
assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), true);

// Do another thing
el.set('nested.obj.value', true);
// Verify
assert.equal(el.$.basic.notifyingValue, true);
assert.equal(el.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.compose.$.basic3.notifyingValue, false);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic3.notifyingValue, false);
assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);

// Do another thing
// no two way binding through negation
el.$.compose.$.basic3.notifyingValue = true;
// Verify
assert.equal(el.$.basic.notifyingValue, true);
assert.equal(el.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.compose.$.basic3.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic1.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic2.notifyingValue, true);
assert.equal(el.$.forward.$.compose.$.basic3.notifyingValue, false);
assert.equal(el.$.basic.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.compose.$.basic3.hasAttribute('attrvalue'), false);
assert.equal(el.$.forward.$.compose.$.basic1.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic2.hasAttribute('attrvalue'), true);
assert.equal(el.$.forward.$.compose.$.basic3.hasAttribute('attrvalue'), false);

});

test('simlarly named properties', function() {
var nested = {
obj: {
Expand Down

0 comments on commit 21383a3

Please sign in to comment.