ich nach ähnlicher Funktionalität bin, und da wir unsere hacky Wege teilen, hier ist meine Geige für Ungeduldige: http://jsfiddle.net/L6axcob8/1/
Diese Geige auf dem einen basieren von @lxe bereitgestellt, mit Updates von @ Kingpin2k und dann von mir selbst.
Ember: 1.9.1, Lenker: 2.0.0, jQuery 2.1.3
Hier haben wir einen Helfer hinzufügen every
genannt, die über Objekte und Arrays laufen kann.
Zum Beispiel dieses Modell:
model: function() {
return {
properties: {
foo: 'bar',
zoo: 'zar'
}
};
}
kann mit dem folgenden Lenker Vorlage wiederholt werden:
<ul class="properties">
{{#every p in properties}}
<li>{{p.key}} : {{p.value}}</li>
{{/every}}
</ul>
every
Helfer funktioniert durch ein Array von den Objekten Schlüssel erstellen und dann die Koordination ändert sich in Ember über einen ArrayController. Ja, hacky. Dies erlaubt uns jedoch, Eigenschaften zu einem Objekt hinzuzufügen/davon zu entfernen, vorausgesetzt, dass das Objekt die Beobachtung der Eigenschaft [] unterstützt.
In meinem Anwendungsfall habe ich eine Ember.Object abgeleitete Klasse, die [] benachrichtigt, wenn Eigenschaften hinzugefügt/entfernt werden. Ich würde empfehlen, Ember.Set für diese Funktionalität zu betrachten, obwohl ich sehe, dass Set vor kurzem veraltet war. Da dies etwas außerhalb des Aufgabenbereichs liegt, überlasse ich es dem Leser als Übung.Hier ein Tipp: setUnknownProperty
Um von Eigenschaftsänderungen benachrichtigt werden wir nicht-Objektwerte wickeln, was ich ein DataValueObserver genannt haben, die einrichtet (zur Zeit eine Art und Weise) Bindungen. Diese Bindungen bieten eine Brücke zwischen den Werten, die von unserem internen ArrayController gehalten werden, und dem Objekt, das wir beobachten.
Beim Umgang mit Objekten; Wir verpacken diese in ObjectProxy, so dass wir ein "Schlüssel" -Mitglied einführen können, ohne das Objekt selbst modifizieren zu müssen. Warum ja, dies bedeutet, dass Sie # reversedly verwenden könnten. Eine weitere Übung für den Leser ;-)
Ich würde empfehlen, dass Ihr Modell auf Ember.Object basiert, um mit dem Rest von Ember konsistent zu sein, so dass Sie Ihr Modell über seine & Set-Handler manipulieren können. Wie in der Geige gezeigt, können Sie Em.Get/Em.set alternativ verwenden, um auf Modelle zuzugreifen, solange Sie dies konsistent tun. Wenn Sie Ihr Modell direkt berühren (no get/set), wird every
nicht über Ihre Änderung benachrichtigt.
Em.set(model.properties, 'foo', 'asdfsdf');
Der Vollständigkeit halber hier ist mein every
Helfer:
var DataValueObserver = Ember.Object.extend({
init: function() {
this._super();
// one way binding (for now)
Em.addObserver(this.parent, this.key, this, 'valueChanged');
},
value: function() {
return Em.get(this.parent, this.key);
}.property(),
valueChanged: function() {
this.notifyPropertyChange('value');
}
});
Handlebars.registerHelper("every", function() {
var args = [].slice.call(arguments);
var options = args.pop();
var context = (options.contexts && options.contexts[0]) || this;
Ember.assert("Must be in the form #every foo in bar ", 3 == args.length && args[1] === "in");
options.hash.keyword = args[0];
var property = args[2];
// if we're dealing with an array we can just forward onto the collection helper directly
var p = this.get(property);
if (Ember.Array.detect(p)) {
options.hash.dataSource = p;
return Ember.Handlebars.helpers.collection.call(this, Ember.Handlebars.EachView, options);
}
// create an array that we will manage with content
var array = Em.ArrayController.create();
options.hash.dataSource = array;
Ember.Handlebars.helpers.collection.call(this, Ember.Handlebars.EachView, options);
//
var update_array = function(result) {
if (!result) {
array.clear();
return;
}
// check for proxy object
var result = (result.isProxy && result.content) ? result.content : result;
var items = result;
var keys = Ember.keys(items).sort();
// iterate through sorted array, inserting & removing any mismatches
var i = 0;
for (; i < keys.length; ++i) {
var key = keys[i];
var value = items[key];
while (true) {
var old_obj = array.objectAt(i);
if (old_obj) {
Ember.assert("Assume that all objects in our array have a key", undefined !== old_obj.key);
var c = key.localeCompare(old_obj.key);
if (0 === c) break; // already exists
if (c < 0) {
array.removeAt(i); // remove as no longer exists
continue;
}
}
// insert
if (typeof value === 'object') {
// wrap object so we can give it a key
value = Ember.ObjectProxy.create({
content: value,
isProxy: true,
key: key
});
array.insertAt(i, value);
} else {
// wrap raw value so we can give it a key and observe when it changes
value = DataValueObserver.create({
parent: result,
key: key,
});
array.insertAt(i, value);
}
break;
}
}
// remove any trailing items
while (array.objectAt(i)) array.removeAt(i);
};
var should_display = function() {
return true;
};
// use bind helper to call update_array if the contents of property changes
var child_properties = ["[]"];
var preserve_context = true;
return Ember.Handlebars.bind.call(context, property, options, preserve_context, should_display, update_array, child_properties);
});
Inspiriert von:
ist hier, dass Geige wieder, wenn Sie es verpasst haben:
Leider Sie gehen auf Probleme stoßen, wo es nicht sehen wird, oder zu aktualisieren ... http://jsfiddle.net/CbV8X/2/ – Kingpin2k
Gibt es eine Möglichkeit, es richtig zu binden, @ Kingpin2k? – lxe
Leider nein, es gibt keine integrierte Funktionalität, die besagt, dass alle Eigenschaften eines Objekts überwacht werden, was zur Implementierung dieser Art von Funktionalität erforderlich wäre – Kingpin2k