Reputation: 1092
Short version: Is there a way to make sure an observer gets notified of a change, no matter what, even if Ember doesn't think a property has changed?
In general, the ember observer pattern works for me, but here I'm stuck. I'm not sure if this is a bug or whatnot, or feature, but something about this bothers me.
I would be very happy with, in this occassion, some form of myinstance.fireNotificationsNoMatterWhat("cache")
, but I can't find something like that in the code. Is there something I'm missing?
Sample code below showing the problem.
<!DOCTYPE html>
<html>
<head>
<title>emberjs notification test</title>
<!-- using current (at the time) version 0.9.5, from emberjs.com
starter kit. -->
<script src="jquery-1.6.1.min.js"></script>
<script src="ember-0.9.5.min.js"></script>
<script>
Test = Ember.Application.create({});
// I don't want an arrayproxy this time, and would be happy to find
// out if there is some form of ObjectProxy?
Test.cacheObject = Ember.Object.create({
"cache": {},
"add": function(key, value) {
// In other situations, I don't need
// propertyWillChange/propertyDidChange, but here
// I'm stuck, and I can't notify listeners when my
// cache changes, so I figured I'd try out
// these commands, which don't work, either.
this.propertyWillChange("cache");
var cache = this.get("cache");
cache[key] = value;
this.set("cache", cache);
this.propertyDidChange("cache");
},
});
// Contrived watcher.
Test.watcher = Ember.Object.create({
// One of the many ways I've tried to bind to the
// the object to get the observer to fire.
"cacheBinding": "Test.cacheObject.cache",
"obs": function() {
// Ideally, whenever I call Test.cacheObject.add in different call
// stacks I should be notified.
console.log("cache has changed:");
console.log(this.get("cache"));
}.observes("cache"),
});
setTimeout(function() {
// I get notified on the first add...
Test.cacheObject.add("hello", "world");
}, 500);
setTimeout(function() {
// ...but I will not get notified on the second, or any subsequent addition.
Test.cacheObject.add("and", "universe");
}, 1000);
</script>
</head>
<body>
<h1>emberjs notification test</h1>
<h2>Please open your console to see the console.log output.</h2>
</body>
</html>
EDIT: It looks like there are short term fixes to this problem, however after trying out my own "fix", and trying out Roy's suggestion below, I think my core question will not be answerable until this enhancement request gets some love from the busy ember team. I can wait for that if it eventually gives me what the ArrayProxy gives me.
Upvotes: 0
Views: 3768
Reputation: 6309
Okay found the problem, and no it's not a bug. What's happening is the hash that Test.cacheObject.cache
is set to is not changing. Basically you aren't changing the actual hash to another hash... you're just changing properties on the same hash in memory.
Take a look at this jsFiddle for a solution, but short version, you only need to change var cache = this.get("cache");
to var cache = {};
edit:
Since data must be perserved the only other thing I can think of is having cache be an array and just assigning it key/value pairs while observing cache.@each
. I've updated the jsFiddle to show this. Hopefully this workaround works for what you're trying to accomplish.
edit2:
See the jsFiddle now. After sleeping a little I thought of a solution that satisfies all of your requirements. Oh and I don't believe in "no solution"... every problem has a solution!
Upvotes: 1