Ich versuche, eine Direktive zu erstellen, die ein Eingabefeld mit demselben ng-Modell wie das Element erstellt, das die Direktive erstellt.
Folgendes habe ich mir bisher ausgedacht:
HTML
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive ng-model="name"></my-directive>
</body>
</html>
JavaScript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'E',
scope: {
ngModel: '='
},
template: '<div class="some"><label for="{{id}}">{{label}}</label>' +
'<input id="{{id}}" ng-model="value"></div>',
replace: true,
require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
$scope.label = attr.ngModel;
$scope.id = attr.ngModel;
console.debug(attr.ngModel);
console.debug($scope.$parent.$eval(attr.ngModel));
var textField = $('input', elem).
attr('ng-model', attr.ngModel).
val($scope.$parent.$eval(attr.ngModel));
$compile(textField)($scope.$parent);
}
};
});
Ich bin jedoch nicht sicher, ob dies der richtige Weg ist, um mit diesem Szenario umzugehen, und es gibt einen Fehler, dass mein Steuerelement nicht mit dem Wert des Zielfelds ng-model initialisiert wird.
Hier ist ein Plunker des obigen Codes: http://plnkr.co/edit/IvrDbJ
Wie geht man damit richtig um?
BEARBEITEN : Nach dem Entfernen der ng-model="value"
aus der Vorlage scheint dies gut zu funktionieren. Ich werde diese Frage jedoch offen halten, da ich überprüfen möchte, ob dies der richtige Weg ist.
scope
und einstellenscope: false
? Wie kann man sichng-model
in diesem Fall binden ?Antworten:
EDIT : Diese Antwort ist alt und wahrscheinlich veraltet. Nur ein Kopf hoch, damit die Leute nicht in die Irre gehen. Ich verwende Angular nicht mehr, daher bin ich nicht in der Lage, Verbesserungen vorzunehmen.
Es ist eigentlich eine ziemlich gute Logik, aber Sie können die Dinge ein wenig vereinfachen.
Richtlinie
HTML mit Direktive
CSS
Sie können es mit diesem Plunker in Aktion sehen .
Folgendes sehe ich:
BEARBEITEN Wie von Mark in seinem Kommentar erwähnt, gibt es keinen Grund, warum Sie das ng-Modell nicht verwenden können , nur um die Konvention einzuhalten.
Im Allgemeinen sollten Ihre Anweisungen den isolierten Bereich verwenden (was Sie korrekt getan haben) und den Bereich vom Typ '=' verwenden, wenn ein Wert in Ihrer Anweisung immer einem Wert im übergeordneten Bereich zugeordnet werden soll.
quelle
contenteditable
Direktivenbeispiele in den Angular-Dokumenten - Formularseite , NgModelController-Seite - verwenden beide ng-model. Auf der Seite ngModelController heißt es, dass dieser Controller "durch andere Anweisungen erweitert werden soll".hg-model
(und nicht das Problem der Kopplung, IMO). Auf diese Weise verwendet der Datenkontext immer das ng-Modell, unabhängig davon, ob es sich um eine<input>
oder eine benutzerdefinierte Direktive handelt, wodurch der kognitive Aufwand für den HTML-Writer vereinfacht wird. Das heißt, es erspart dem HTML-Writer, herauszufinden, wie der Namemy-directive-var
für jede Direktive lautet, zumal es keine automatische Vervollständigung gibt, die Ihnen hilft.ng-model-options
oder einem der anderen ng-Modellsachen, oder?Ich habe eine Kombination aller Antworten erstellt und habe jetzt zwei Möglichkeiten, dies mit dem Attribut ng-model zu tun:
Code-Snippet anzeigen
Ich bin mir nicht sicher, ob mir das Kompilieren zur Linkzeit gefällt. Wenn Sie das Element jedoch nur durch ein anderes ersetzen, müssen Sie dies nicht tun.
Alles in allem bevorzuge ich den ersten. Stellen Sie einfach den Bereich auf
{ngModel:"="}
und legenng-model="ngModel"
Sie fest, wo Sie ihn in Ihrer Vorlage haben möchten.Update : Ich habe das Code-Snippet eingefügt und es für Angular v1.2 aktualisiert. Es stellt sich heraus, dass der isolierte Bereich immer noch am besten ist, insbesondere wenn jQuery nicht verwendet wird. Es läuft also darauf hinaus:
Ersetzen Sie ein einzelnes Element: Ersetzen Sie es einfach, lassen Sie den Bereich in Ruhe, aber beachten Sie, dass das Ersetzen für Version 2.0 veraltet ist:
Andernfalls verwenden Sie Folgendes:
quelle
ng-model
in einem isolierten Bereich geben?es ist nicht so kompliziert: Verwenden Sie in Ihrem Verzeichnis einen Alias:
scope:{alias:'=ngModel'}
Verwenden Sie in Ihrem HTML wie gewohnt
quelle
Sie benötigen ng-model nur, wenn Sie auf $ viewValue oder $ modelValue des Modells zugreifen müssen. Siehe NgModelController . Und in diesem Fall würden Sie verwenden
require: '^ngModel'
.Für den Rest siehe Roys Antwort .
quelle
^
sollte nur da sein, wenn das ng-Modell in einem übergeordneten Element angewendet wirdDies ist ein wenig zu spät Antwort, aber ich fand diese tolle Post über
NgModelController
, was ich denke , ist genau das, was Sie suchen.TL; DR - Sie können Folgendes verwenden
require: 'ngModel'
und dannNgModelController
zu Ihrer Verknüpfungsfunktion hinzufügen :Auf diese Weise sind keine Hacks erforderlich - Sie verwenden das integrierte Angular
ng-model
quelle
Ich würde das ngmodel nicht über ein Attribut festlegen, Sie können es direkt in der Vorlage angeben:
Plunker : http://plnkr.co/edit/9vtmnw?p=preview
quelle
Seit Angular 1.5 können Komponenten verwendet werden. Komponenten sind der richtige Weg und lösen dieses Problem auf einfache Weise.
In YourController müssen Sie lediglich Folgendes tun:
quelle
input ng-model="$ctrl.ngModel"
und es wird auch mit $ ctrl.result synchronisiert.Das Erstellen eines isolierten Bereichs ist unerwünscht. Ich würde die Verwendung des Bereichsattributs vermeiden und so etwas tun. scope: true gibt Ihnen einen neuen untergeordneten Bereich, der jedoch nicht isoliert wird. Verwenden Sie dann parse, um eine lokale Bereichsvariable auf dasselbe Objekt zu verweisen, das der Benutzer dem ngModel-Attribut übergeben hat.
quelle