Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AT: misusing setValue
{
"name": "AT: misusing setValue",
"description": "",
"data": {
"myContainer": {
"magicValue": 7
}
}
}
{macro main()}
<button {on click "updateModelBad" /}>Update (bad)</button>
<button {on click "updateModelStillBad" /}>Update (even worse)</button>
<button {on click "updateModelBetter" /}>Update (best)</button>
<br>
Magic value is: {@aria:Text {
bind : {
text : {
inside: this.data.myContainer,
to: "magicValue"
}
}
}/}
<hr>
<p>1. The 'bad' button operation retrieves a reference to 'myContainer' object, modifies the object, and then assigns back this reference to the data model entry. It's basically equivalent to this code:
<pre>
var a, b;
a = \{\};
b = a;
b.someProperty = 42;
a = b;
</pre>
It's just juggling the references, <code>a</code> is still the same object after the last assignment. The last operation doesn't really change anything; both <code>a</code> and <code>b</code> are references to the very same object already, so last action is essentally a NOOP.
<hr>
<p>2. The 'even worse' button tries to circumvent the issue from point 1) by creating a new object, instead of modifying the existing one. This however creates other problems.
Our Text widget is bound to <code>magicValue</code> of <code>this.data.myContainer</code> object at the time of its first evaluation.
the line
<pre>
this.$json.setValue(this.data, "myContainer", c);
</pre>
is equivalent in this context to
<pre>
this.data.myContainer = \{...\}
</pre>
In other words, we're destroying the reference to the original object, to which the widget is bound. Now the data model contains a completely new object, while the widget is still hoping to see updates to the old object, but that reference is lost, so no updates will ever occur any more.
<br><br>
<hr>
<p>
3. The 'best' button implements things correctly - it doesn't change the reference to the original object, but it mutates the <em>properties</em> of that object.<br><br>
<strong>Note that The last button implements the correct behavior, but after clicking the middle button first, it won't work, because it will try to update, though correctly, not the proper object that the widget is observing.</strong> If the last button is not working fine for you, you have to refresh the page.
{/macro}
({
$classpath:'InstantTemplateScript',
$prototype : {
updateModelBad: function() {
var c = this.data.myContainer;
c.magicValue = 42;
c.otherValue = 888;
this.$json.setValue(this.data, "myContainer", c);
},
updateModelStillBad: function() {
var c = {
magicValue: 42,
otherValue : 888
};
this.$json.setValue(this.data, "myContainer", c);
},
updateModelBetter: function() {
this.$json.setValue(this.data.myContainer, "magicValue", 42);
this.$json.setValue(this.data.myContainer, "otherValue", 888);
}
}
})
{macro main()}
{/macro}
@jakub-g

This comment has been minimized.

Copy link
Owner Author

commented Oct 17, 2014

Created by Instant Aria Templates, viewable on http://instant.ariatemplates.com/jakub-g/32ee1cac71358ee829fe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.