Bindung ngModel, um eine benutzerdefinierte Richtlinie
So habe ich die Arbeit an diesem Thema für eine Woche jetzt und ich kann nicht scheinen, um meinen Kopf um diese ganze Richtlinie Sache. Ich habe gelesen, viele Beiträge ...
einen Haufen videos ...
Gegangen und durch StackOverflow und in anderen Foren (links Folgen) in der Hoffnung, etwas untergehen wird, in ... ich denke, dass das problem, dass ich laufen bin, ist, dass ich möchte, um zu VERSTEHEN, warum/wie diese Arbeit, so dass ich mich nicht Ausschneiden/einfügen, jemand anderes die Lösung in meinem code, aber dann haben später noch einmal Fragen, wenn etwas anderes auftaucht, weil ich nicht weiß, was meine eingefügten code tut.
Ich finde aber jeder hat einen anderen Weg, um der Haut diese Katze und keiner von Ihnen scheinen zu passen mit meinem Verständnis, WIE das funktionieren soll.
Was ich bin versucht zu tun ist erstellen Sie ein Formular mit dem Metro UI CSS Bibliothek. Ich dachte, ich würde anfangen mit einem einfachen text-box. yep ... nur ein einfach Textfeld. Eine Metro-UI-text-box hat einige nette eingebaute Funktionen, die ich wollte zu bewahren, so dass ich dachte, dass war ein guter Ausgangspunkt.
Habe ich gelesen, dass zu nutzen, um die Metro UI-Verhaltensweisen, die mit AngularJS ich brauchen würde, um wickeln Sie es in eine benutzerdefinierte Richtlinie (Benutzerdefinierte Daten-Richtlinien innerhalb einer AngularJS ng-repeat). Während dieses Beispiel war nicht genau das, was ich suchte, schien es leicht zu erklären, was ich tun musste. Rufen Sie einfach die Funktion, gilt das Verhalten in der LINK-Funktion der Richtlinie und fügen die Richtlinie Attribut auf das input-element ...
So habe ich eine Richtlinie namens 'metroInputTransform" und fügte hinzu, es als Attribut zu einem input-element.
<div data-ng-controller="pageOneFormCtrl as page">
<input type="text" id="txProductName"
data-ng-model="page.data.productName"
data-metro-input-transform=""
placeholder="product name" />
</div>
In der LINK-Funktion der Direktive, die ich einfach als die Methode, gilt das Verhalten, das ich suchte. Ich weiß, dass dies ein wenig Ausführlicher ist, als es sein muss, aber ich versuche zu lernen, so dass ich einen Schritt durch Sie, so gut ich kann. ... (für den vollständigen code siehe diese Geige)
var metroDirectives = angular.module('metroDirectives', []);
metroDirectives.directive('metroInputTransform', function ($compile) {
function postLink($scope, element, attrs, controller) {
$(element).inputTransform();
};
return {
priority: 100,
compile: function (element, attrs) {
return { postLink };
}
};
});
So, das hat funktioniert, teilweise. Es erstellt die Metro-look-and-feel und damit verbundenen Verhalten, aber ... ngModel war nicht die Bindung an das element. So begann eine lange Reise durch Konzepte wie isolieren Umfang aus, indem Sie die verschiedenen compile -, controller -, pre-link -, post-link-Funktionen, die mindestens zwei verschiedene Arten von persistierenden ngModel ... all das hat nicht funktioniert.
Nachdem eine Vielzahl der lese-es war mein Verständnis, dass die DOM-manipulation passieren sollte in der COMPILE-Funktion, so dass alle DOM-Transformationen zur Verfügung stehen würde für das kompilieren und verknüpfen Phasen des digest-Prozess. Also zog ich die inputTransform () - Aufruf an die COMPILE-Funktion ... (fiddle)
return {
priority: 100,
terminal: true, //if I didn't put this everything would execute twice
compile: function (element, attrs) {
$(element).inputTransform();
return {
pre: preLink,
post: postLink
};
}
};
Kein Glück ... dasselbe ... nicht die Bindung an ngModel. So entdeckte ich das Konzept der "isolieren Umfang" ...
- Verständnis Isolieren Umfang - video
- Mit Isolieren Bereiche, die in der Richtlinie - video
- Mit ngModel mit Isolieren Umfang
Basiert auf der, die ich habe versucht, die folgenden (fiddle)...
return {
priority: 100,
scope: {
ngModel : '='
},
terminal: true, //if I didn't put this everything would execute twice
compile: function (element, attrs) {
$(element).inputTransform();
return {
pre: preLink,
post: postLink
};
}
};
Nicht ändern ...
Habe ich versucht, eine Reihe von anderen Dingen, aber fürchte, dass ich möglicherweise verlieren Sie die Aufmerksamkeit, bald, wenn ich nicht bereits haben. Der nächstgelegene ich bekam, war die einseitige Bindung etwas wie unten ... und auch hier kann man sehen, dass die Extraktion der ngModel Referenz ist völlig inakzeptabel. (fiddle)
var metroDirectives = angular.module('metroDirectives', []);
metroDirectives.directive('metroInputTransform', function () {
function postLink($scope, element, attrs, controller) {
//
//Successfully perfomes ONE-WAY binding (I need two-way) but is clearly VERY
//hard-coded. I suppose I could write a pasrsing function that would do this
//for whatever they assign to the ngModel ... but ther emust be a btter way
$(element).on("change", '[data-metro-input-transform]', function(e) {
$scope.$apply(function(){
$scope['page']['data']['productName'] = e.currentTarget.value;
});
});
};
return {
priority: 100,
terminal: true, //if I didn't put this here the compile would execute twice
compile: function (element, attrs) {
$(element).inputTransform();
return {
pre: function ($scope, element, attrs, controller, transcludeFn) { },
post: postLink
};
}
};
});
Bin ich ERSCHÖPFT und habe absolut keine Ahnung, was übrig ist, um zu versuchen. Ich weiß, dass dies eine Frage ist, von meiner Unwissenheit und Mangel an Verständnis, wie/warum AngularJS funktioniert, wie es funktioniert. Aber jeder Artikel, den ich gelesen habe lässt mich Fragen so viele Fragen, die so beantwortet wurden, oder nimmt mich unten ein Kaninchenbau, in denen ich mehr verloren, als ich war, als ich begonnen. Kurz ablegen von $3000 auf live in-person-Seminare, die ich mir nicht leisten kann, wo ich kann, bitten, die Fragen muss ich beantwortet haben, ich bin in einer kompletten Sackgasse mit Angular.
Ich wäre sehr dankbar, wenn jemand könnte geben Orientierung, Richtung ... eine gute Ressource, ... alles kann helfen, etwas Licht auf dieses Thema, insbesondere, aber alles, was helfen könnte mich aufhören zu Spinnen meine Räder. In der mean-time-werde ich weiter Lesen und wieder-Lesen alles, was ich finden kann, und hoffen, dass sich etwas brechen.
Dank
G
UPDATE - 10/30/2014
Ich bin soooo über dieses Problem, aber wollen Folgen Sie durch. Ich muss und will lernen. Auch ich möchte wirklich dankbar für die Mühe, die Leute in Sie setzen, und während Sie haben einige Lösungen, die letztlich möglicherweise der beste Weg zu gehen, Sie haben beide umging das Problem ist, dass ich bin versucht, das Verhalten mit der Metro UI CSS-Bibliothek. Ich würde lieber nicht haben, umschreiben Sie Sie, wenn möglich.
Beide Lösungen so weit beseitigt haben, die key-Anweisung aus der Lösung ... das ist die Zeile ...
$(element).inputTransform()
Ich nicht buchen möchten, die gesamte jQuery-widget, umfasst die "inputTransform" definition, aber ich Schneide das Fleisch es heraus und schlossen es hier ...
function createInputVal(element, name, buttonName) {
var wrapper = $("<div/>").addClass("input-control").addClass(name);
var button = $("<button/>").addClass(buttonName);
var clone = element.clone(true); //clone the original element
var parent = element.parent();
$(clone).appendTo(wrapper);
$(button).appendTo(wrapper);
$(wrapper).insertBefore(element);
$(element).remove(); //delete the original element
return wrapper;
};
So, ich habe das auf die Direktive als Attribut, denn die Metro code dahinter will KLONEN Sie die text-box (das nicht tun würde, wenn es ein element-Richtlinie) und ENTFERNT anschließend das original-input-element. Es erstellt dann das neue DOM-Elemente und schließt die geklonten input-element in das neu erzeugte DIV-container. Der Fang, den ich glaube, ist ... dass die Bindung gebrochen, als das ursprüngliche element wird geklont und aus dem DOM entfernt. Macht Sinn, wenn die "ng-model" Attribut-Zuordnung wird an eine Referenz der text-box. So die Erwartung, die ich ursprünglich hatte war, da der "ng-model" Attribut wurde kloniert und zusammen mit dem rest des Elements, das in der compile-Ereignis/Funktion/phase der Richtlinie, die Referenz wäre(wieder -) gegründet, um die neu erstellte input-element. Dies war anscheinend nicht der Fall ist. Sehen Sie in dieser aktualisierten fiddle, die ich gemacht habe einige versuche der Wiederverbindung der ng-model auf die neue DOM-Elemente ohne Erfolg.
Vielleicht ist dies unmöglich ... es scheint sicher, dass nur re-building diese Dinge können letztlich den einfacheren Weg zu gehen.
Nochmals vielen Dank Mikko Viitalia und 'azium' ...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Richtlinien sind nicht die einfachsten Konzepte gibt, und die Dokumentation ist wirklich nicht gut und es ist verstreut auf der ganzen interwebs.
Kämpfte ich mit
compile
,pre-compile
und wie, wenn ich versuchte zu schreiben, meine ersten Richtlinien, aber bisher habe ich noch nie benötigt diese Funktionen. Es könnte sein, aufgrund meiner mangelnden Verständnis, aber immer noch...Blick auf Ihre Beispiele, die ich sehen, es gibt einige grundlegende Dinge, die zu klären. Zunächst, ich würde verhindern, dass Ihre Richtlinie zu
E
lement, da es ersetzt das Steuerelement in HTML. Ich würde verwendenA
ttribute z.B. zum hinzufügen von Funktionalität zu existierenden Kontrolle.Gibt es eine (Pflicht) naming convention, wo Sie mit gestrichelten Benennung in HTML und camel casing inside Ihr JavaScript. So
something-cool
wirdsomethingCool
. Wenn Sie "binden" die Variablen der Richtlinie ist der Umfang, es gibt einen großen Unterschied, wie Sie es tun. Mit=
Sie bind-Variablen, mit@
Variablen ausgewertet (string -) Wert. Also Erstens ermöglicht die "two-way-binding" - aber letzteres natürlich nicht. Sie können auch&
zu binden übergeordneten Bereich Ausdruck/Funktion.Wenn Sie z.B. plain
=
dann-Richtlinie Umfang erwartet gleichen Namen in den HTML-Code. Wenn Sie möchten, verwenden Sie unterschiedliche Namen, dann fügen Sie die variable name nach der=
. Ein BeispielIch nahm mir die Freiheit zu nehmen Ihre erste Geige von
metro-input-transform
als Ausgangspunkt und schreiben Sie es in Plunker. Versuche ich es hier erklären (und hoffe, dass ich Sie richtig verstanden).U-Bahn-Eingang Richtlinie
Richtlinie erwartet
ngModel
zu binden undwatermark
zu zeigen, wenn ngModel hat keinen Wert (text Eingabe leer ist). Innerhalblink
habe ich eingeführtclear()
- Funktion, die verwendet wird, innerhalb der Richtlinie zum zurücksetzenngModel
. Wenn der Wert zurückgesetzt wird,watermark
zeigen. Ich haben sich getrennt, die HTML-Teile in eine separate Datei, metro-template.html.U-Bahn-input-HTML-Vorlage
Hier binden wir
ngModel
zur Eingabe und zuweisenplaceholder
. Button mit [X] gebunden istclear()
Methode.Nun, wenn wir unsere Richtlinie eingerichtet, hier ist der HTML-Seite verwenden.
HTML-Seite
Also im obigen Beispiel für die Verwendung von metro-Richtlinie, ist wie folgt. Diese werden ersetzt durch Richtlinie ist HTML-Vorlage.
Den anderen Eingang hat
detect-mouse-over
Richtlinie angewendet wurde, beschränkt sich aufA
ttribute nur um zu zeigen, Nutzungen/Unterschiede zwischenA
undE
. Maus-detection-Richtlinie macht die Eingabe ändern Sie hintergrund-Farbe, wenn die Maus bewegt wird über/raus..
Es hat auch die gleichen
ng-model
spiegeln Veränderungen zwischen den Kontrollen.In Ihrem Beispiel, Sie hatten auch einen
productService
vorausgesetzt, dass der Wert über input-Kontrollen. Ich schrieb es alsProdukt-service -
So
get()
Funktion wird nur die hart codierten Wert, aber es immer noch demonstriert die Verwendung der Dienste. Controller, benanntCtrl
ist wirklich simpel. Wichtiger Bestandteil hier ist, dass Sie sich daran erinnern, um zu injizieren, alle Dienste und solche in den controller. In diesem Fall eckig ist$scope
und unsere eigenenproductService
.Controller
Hier ein screen-capture der obigen Lösung.
Ändern Wert in einem der Eingänge ändert sich der Wert von beiden. Eingang unten hat "mouseover" also, es ist Grau, mouseout würde schalten Sie es wieder weiß. Drücken Sie [X] löscht den Wert und die macht der Platzhalter sichtbar.
Hier ist der link zu plunker einmal mehr http://plnkr.co/edit/GGGxp0
Ok, ich bin mir nicht genau sicher, was andere Vorteile aus der Metro UI, du bist immer, aber hier ist eine einfache Geige, die nicht brauchen, Ihre Richtlinie überhaupt zu erfassen, was Sie hatte in Ihrer ersten Geige, die für mich funktioniert. http://jsfiddle.net/f0sph1vp/7/
Die zweite Geige, die Sie geschrieben, http://jsfiddle.net/gary_stenstrom/xcx2y8uk/64/, ist ziemlich seltsam für mich, weil es nicht scheinen, wie Sie wollen, der zweite input Feld das gleiche Modell wie das erste. Es scheint, wie Sie wollen, dass der Klick auf die x-Taste, um den Wert zuzuweisen, der den ersten Eingang auf den zweiten. Das macht viel mehr Sinn.