greg
I wonder if it wouldn't be easier to just add an optional argument to $$() to cause it to listen to events triggered by all objects, not just triggered on it directly..var btn = $$(true, {}, '<div><button>Cancel operation</button></div>', { 'persist:stop': function() { $(this).remove(); }});
t
Today I had time to re-look at my issue of “one model bound to multiple views.”
For me, the use case is trivial – persistent application state data including user modified and/or default application settings. Some of these data are used in multiple agility UI-view objects. Current page and total pages for instance; or theming data perhaps.
Anyway, I wanted agility to handle the data-binding where appropriate without undue application code for special cases.
Firstly, I hope that someone more experienced than I is considering this issue and able to incorporate a general solution into agility.js. Meantime I made a simple work around that seems to play well in my limited testing. I'll attach a file for anyone interested.
In short, I made a small change to agility.js, reluctantly. The change to agility was in the model's setter method 'set' to insure that the change events are only fired if there is an actual difference between the proposed new value and the current model stored value. The issue is a 'feedback loop' of continuous change events when simply setting the data via the model set and change event.
First I made an agility object called 'global_data' defining a model and a controller:
var global_data = $$({
model : { name : 'Greg Baker' },
controller : {
'change:name' : function(event,obj) {
obj1.model.set({'name':this.model.get('name')});
obj2.model.set({'name':this.model.get('name')});
}
}
});
The intent is that upon change of the global_data's name field, two other object models, obj1 and obj2, are also 'manually' updated. Not cool, but not too much extra wiring.
Obj1 and obj2 are identical. Both are simple agility objects that use the global_data object as a prototype. Their model is actually merged with a local copy of the global_data's model. Their view is an input field with echo display (plagiarized from the agility documentation examples.) The controller monitors the user 'keystrokes' to the input field and for each keystroke, forces a data change event. The change even propagates back to the global_data model where it is echoed back to both obj1 and obj2.
Here is that code fragment:
var obj1 = $$(global_data, {
model: { title : "Obj1's value: " },
view : {
format : '<p><input type="text" data-bind="name" ' +
'autocomplete="off" placeholder="Enter name." /> ' +
'<b><span data-bind="title"/></b> ' +
'<span data-bind="name"/>'
},
controller : {
'keyup input' : function(event) {
this.view.$('input').change();
if (event.which == 13) this.view.$('input').blur();
}
}
});
The second object is identical except it is named 'obj2'.
Now, where ever and when ever 'name' is updated, all references are updated. So we can modify the global_data's controller to save our persistent data knowing it will always be current.
Remember to modify a local copy of agility.js for testing the attached file. The necessary changes are detailed in the attached file at the bottom as an HTML comment. This is a quick summary:
...
else {
// Commented out the next line.
//$.extend(this.model._data, arg);
}
for (var key in arg) {
delete _clone[ key ];
// Check for 'actual' change in the value.
if ( this.model._data[key] != arg[key] ) {
this.model._data[key] = arg[key];
modified.push(key);
}
}
...