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" ...

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' ...

Schreibe einen Kommentar