Es gibt zahlreiche Fragen, die auf die eine oder andere Art fragen: "Wie mache ich etwas, nachdem ein Teil einer Ansicht gerendert wurde?" ( hier , hier und here nur um ein paar zu geben). Die Antwort lautet normalerweise:
didInsertElement
, um Code auszuführen, wenn eine Ansicht anfänglich gerendert wird. Ember.run.next(...)
, um Ihren Code auszuführen nachdem die Änderungen der Ansicht geleert wurden, wenn Sie auf die erstellten DOM-Elemente zugreifen müssen. isLoaded
oder eine ähnliche Eigenschaft, um etwas nach dem Laden der Daten zu tun, die Sie laden müssen. Was daran irritiert, ist, dass es zu sehr ungeschickt aussehenden Dingen wie diesem führt:
%Vor% Und das funktioniert nicht unbedingt, wenn Sie ember-data verwenden, da isLoaded
möglicherweise bereits wahr ist (wenn der Datensatz bereits zuvor geladen wurde und nicht erneut vom Server angefordert wird). Also ist es schwierig, die Sequenzierung richtig zu machen.
Außerdem sehen Sie wahrscheinlich bereits isLoaded in Ihrer Ansichtsvorlage wie folgt:
%Vor%und Wiederholung in Ihrem Controller scheint wie Duplikation.
Ich habe eine etwas neue Lösung gefunden, aber es muss entweder funktionieren oder ist eigentlich eine schlechte Idee ... jeder Fall könnte stimmen:
Ich habe einen kleinen Lenker-Helper namens {{fire}}
geschrieben, der ein Ereignis mit einem benutzerdefinierten Namen auslöst, wenn die enthaltende Lenkervorlage ausgeführt wird (dh das sollte jedes Mal sein, wenn die Teilansicht erneut gerendert wird, richtig?).
Hier ist mein sehr früher Versuch:
%Vor%was wie folgt verwendet wird:
%Vor%Das funktioniert im Wesentlichen wie es ist, aber es hat ein paar Fehler, die ich schon kenne:
{{fire typeaheadHostDidRender target="view"}}
ausprobiert und das hat nicht funktioniert. Ich kann noch nicht sehen, wie man die "aktuelle" Ansicht von dem bekommt, was in den Helfer gelangt ist, aber offensichtlich kann der {{view}}
-Helfer es tun. .trigger()
scheint nicht auf Controller-Objekte zu funktionieren, obwohl es möglicherweise auf Ansichten funktioniert. Gibt es einen "Ember" Weg, dies zu tun? Wie Sie vielleicht raten können, verwende ich das Typeahead-Steuerelement von Bootstrap und muss es verbinden, nachdem das <input>
gerendert wurde. Dies geschieht erst, nachdem mehrere verschachtelte {{#if}}
Blöcke in meiner Vorlage als true ausgewertet wurden . Ich benutze auch jqPlot, so dass ich oft auf dieses Muster stoße. Dies scheint ein praktikables und nützliches Werkzeug zu sein, aber es könnte sein, dass mir etwas großes Bild fehlt, das diesen Ansatz dumm macht. Oder gibt es eine andere Möglichkeit, dies zu tun, die bei meinen Suchen nicht aufgetaucht ist?
Kann jemand diesen Ansatz für mich verbessern oder mir sagen, warum es eine schlechte Idee ist?
Ich habe ein paar der Bits rausgefunden:
options.data.view.get('parentView')
... erhalten, aber vielleicht hätte ich das nicht so einfach gehalten. obj.trigger(evtName)
für jedes beliebige Objekt erstellen ... aber das Objekt muss Ember.Evented
mixin erweitern! Ich nehme an, es ist der richtige Weg, diese Art von Ereignis in Ember zu senden. Stellen Sie nur sicher, dass das beabsichtigte Ziel Ember.Evented
(Ansichten bereits) erweitert. Hier ist die verbesserte Version:
%Vor%Jetzt fehlt mir nur noch die Frage, wie ich das beabsichtigte Ziel einbringen kann (z. B. den Controller oder die Ansicht - der obige Code versucht zu erraten). Oder herausfinden, ob es ein unerwartetes Verhalten gibt, das das ganze Konzept durchbricht.
Irgendwelche anderen Eingaben?
Aktualisiert für Ember 1.0 final, ich verwende diesen Code derzeit in Ember 1.3.1.
Okay, ich denke, ich habe alles herausgefunden. Hier ist der "komplette" Lenkerhelfer:
%Vor% Ich habe den Namen von {{fire}}
in {{trigger}}
geändert, damit er besser der Ember.Evented / jQuery-Konvention entspricht. Dieser aktualisierte Code basiert auf dem integrierten Hilfsprogramm Ember {{action}}
und sollte in der Lage sein, jedes target="..."
Argument in Ihrer Vorlage zu akzeptieren, genauso wie {{action}}
. Wo es sich von {{action}}
unterscheidet (abgesehen davon, dass es automatisch ausgelöst wird, wenn der Template-Abschnitt gerendert wird):
actions: {…}
Hash!) Beachten Sie, dass Sie, wenn Sie ein Ereignis an eine Instanz von Ember.View senden, lediglich eine Methode mit dem gleichen Namen implementieren müssen (siehe Dokumente , Code ). Wenn Ihr Ziel jedoch keine Ansicht ist (z. B. ein Controller), müssen Sie einen Listener für das Objekt mit obj.on('evtName', function(evt){...})
oder der Erweiterung Function.prototype.on
registrieren.
Hier ist ein Beispiel aus der Praxis. Ich habe eine Ansicht mit der folgenden Vorlage, die Ember und Bootstrap verwendet:
%Vor%Ich musste wissen, wann dieses Element im DOM verfügbar war, also konnte ich einen Typeahead anhängen:
%Vor% Also habe ich einen {{trigger}}
Helfer in den selben Block geschrieben:
Und dann didRenderSubjectPicker
in meiner View-Klasse implementiert:
Fertig! Jetzt wird der Typeahead verdrahtet, wenn (und nur wenn) der Unterabschnitt der Vorlage schließlich gerendert wird. Beachten Sie den Unterschied im Dienstprogramm, didInsertElement
wird verwendet, wenn die main (oder vielleicht "konkrete" ist der richtige Begriff) Ansicht gerendert wird, während didRenderSubjectPicker
wird ausgeführt, wenn der Unterabschnitt der Ansicht wird gerendert.
Wenn ich das Ereignis stattdessen direkt an den Controller senden wollte, ändere ich einfach die Vorlage, um zu lesen:
%Vor%und mache das in meinem Controller:
%Vor%Fertig!
Der einzige Vorbehalt besteht darin, dass dies wieder passieren kann , wenn der Ansichtsunterabschnitt bereits auf dem Bildschirm angezeigt wird (z. B. wenn eine übergeordnete Ansicht erneut gerendert wird). Aber in meinem Fall ist das Ausführen der typeahead-Initialisierung immer noch in Ordnung, und es wäre ziemlich einfach, wenn nötig zu erkennen und zu codieren. Und dieses Verhalten kann in einigen Fällen erwünscht sein.
Ich gebe diesen Code als Public Domain heraus, keine Garantie oder Haftung, egal wie. Wenn Sie das verwenden möchten oder die Ember-Leute es in die Baseline aufnehmen wollen, gehen Sie weiter! (Ich persönlich denke, das wäre eine großartige Idee, aber das ist nicht überraschend.)
Tags und Links ember.js