Ich möchte meine Formularfelder in einer Direktive kapseln, damit ich dies einfach tun kann:
<div ng-form='myForm'>
<my-input name='Email' type='email' label='Email Address' placeholder="Enter email" ng-model='model.email' required='false'></my-input>
</div>
Wie greife ich auf das myForm
in meiner Direktive zu, um Validierungsprüfungen durchführen zu können, z myForm.Email.$valid
.
Antworten:
So greifen Sie in einer Direktive auf den FormController zu:
require: '^form',
Dann wird es als 4. Argument für Ihre Link-Funktion verfügbar sein:
link: function(scope, element, attrs, formCtrl) { console.log(formCtrl); }
fiddle
Möglicherweise benötigen Sie jedoch nur Zugriff auf den NgModelController:
require: 'ngModel', link: function(scope, element, attrs, ngModelCtrl) { console.log(ngModelCtrl); }
fiddle
Wenn Sie Zugriff auf beide benötigen:
require: ['^form','ngModel'], link: function(scope, element, attrs, ctrls) { console.log(ctrls); }
fiddle
quelle
'^form'
aber nicht mit'^ngForm'
? Ich habe versucht, das zum ersten Mal zum Laufen zu bringen, aber es kam zu einem Fehler "kein Controller". Ich mag deine Antwort viel besser als meine.form
oderng-form
Direktive im HTML gefunden wird,form
eher alsngForm
. Ich brauchte ein paar Versuche, um herauszufinden, dass der Name istform
. Ich denke, dies ist der Angular-Quellcode, in dem wir sehen, dass erform
verwendet wird.scope.formCtrl = formCtrl;
, dann können Sie in Ihrem Controller darauf zugreifen, indem Sie$scope
:controller: function($scope) { ... }
. Beachten Sie jedoch, dass Ihr Direktiven-Controller zuerst ausgeführt wird, sodass die Referenz nicht vorhanden ist, wenn die Controller-Funktion zum ersten Mal ausgeführt wird.Hier ein vollständiges Beispiel (mit Bootstrap 3.1 gestaltet)
Es enthält ein Formular mit mehreren Eingaben (Name, E-Mail, Alter und Land). Name, E-Mail-Adresse und Alter sind Richtlinien. Land ist eine "normale" Eingabe.
Für jede Eingabe wird eine Hilfemeldung angezeigt, wenn der Benutzer keinen korrekten Wert eingibt.
Das Formular enthält eine Schaltfläche zum Speichern, die deaktiviert ist, wenn das Formular mindestens einen Fehler enthält.
<!-- index.html --> <body ng-controller="AppCtrl"> <script> var app = angular.module('app', []); app.controller('AppCtrl', function($scope) { $scope.person = {}; }); </script> <script src="inputName.js"></script> <script src="InputNameCtrl.js"></script> <!-- ... --> <form name="myForm" class="form-horizontal" novalidate> <div class="form-group"> <input-name ng-model='person.name' required></input-name> </div> <!-- ... --> <div class="form-group"> <div class="col-sm-offset-2 col-sm-4"> <button class="btn btn-primary" ng-disabled="myForm.$invalid"> <span class="glyphicon glyphicon-cloud-upload"></span> Save </button> </div> </div> </form> Person: <pre>{{person | json}}</pre> Form $error: <pre>{{myForm.$error | json}}</pre> <p>Is the form valid?: {{myForm.$valid}}</p> <p>Is name valid?: {{myForm.name.$valid}}</p> </body> // inputName.js app.directive('inputName', function() { return { restrict: 'E', templateUrl: 'input-name.html', replace: false, controller: 'InputNameCtrl', require: ['^form', 'ngModel'], // See Isolating the Scope of a Directive http://docs.angularjs.org/guide/directive#isolating-the-scope-of-a-directive scope: {}, link: function(scope, element, attrs, ctrls) { scope.form = ctrls[0]; var ngModel = ctrls[1]; if (attrs.required !== undefined) { // If attribute required exists // ng-required takes a boolean scope.required = true; } scope.$watch('name', function() { ngModel.$setViewValue(scope.name); }); } }; }); // inputNameCtrl app.controller('InputNameCtrl', ['$scope', function($scope) { }]);
quelle
Bearbeiten 2: Ich werde meine Antwort hinterlassen, da sie aus anderen Gründen hilfreich sein könnte, aber die andere Antwort von Mark Rajcok ist das, was ich ursprünglich tun wollte, aber nicht zur Arbeit kam. Anscheinend wäre der übergeordnete Controller hier
form
nichtngForm
.Sie können es mit einem Attribut in Ihrer Direktive übergeben, obwohl dies ziemlich ausführlich wird.
Beispiel
Hier ist eine funktionierende, vereinfachte jsFiddle .
Code
HTML:
<div ng-form="myForm"> <my-input form="myForm"></my-input> </div>
Wesentliche Teile der Richtlinie:
app.directive('myInput', function() { return { scope: { form: '=' }, link: function(scope, element, attrs) { console.log(scope.form); } }; });
Was ist los
Wir haben Angular gebeten, den im
form
Attribut genannten Bereichswert mithilfe von a an unseren isolierten Bereich zu binden'='
.Auf diese Weise wird die tatsächliche Form von der Eingabeanweisung entkoppelt.
Hinweis: Ich habe versucht, zu verwenden
require: "^ngForm"
, aber die ngForm-Direktive definiert keinen Controller und kann nicht auf diese Weise verwendet werden (was zu schade ist).Trotzdem denke ich, dass dies eine sehr ausführliche und unordentliche Art ist, damit umzugehen. Es ist möglicherweise besser, dem Formularelement eine neue Direktive hinzuzufügen und
require
auf dieses Element zuzugreifen. Ich werde sehen, ob ich etwas zusammenstellen kann.Bearbeiten: Verwenden einer übergeordneten Direktive
OK, hier ist das Beste, was ich mit einer übergeordneten Direktive herausfinden kann. Ich werde gleich mehr erklären:
Arbeits jsFiddle Mutter Direktive
HTML:
<div ng-app="myApp"> <div ng-form="theForm"> <my-form form="theForm"> <my-input></my-input> </my-form> </div> </div>
JS (teilweise):
app.directive('myForm', function() { return { restrict: 'E', scope: { form: '=' }, controller: ['$scope', function($scope) { this.getForm = function() { return $scope.form; } }] } }); app.directive('myInput', function() { return { require: '^myForm', link: function(scope, element, attrs, myForm) { console.log(myForm.getForm()); } }; });
Dadurch wird das Formular im Bereich der übergeordneten Direktive (
myForm
) gespeichert , und untergeordnete Direktiven können darauf zugreifen, indem sie das übergeordnete Formular (require: '^myForm'
) benötigen und in der Verknüpfungsfunktion (myForm.getForm()
) auf den Controller der Direktive zugreifen .Leistungen:
Negative:
Was ich bevorzugen würde
Ich habe versucht, es mithilfe eines Attributs für das Formularelement zum Laufen zu bringen . Wenn dies funktioniert, müssen Sie die Direktive nur demselben Element wie hinzufügen
ngForm
.Ich bekam jedoch ein seltsames Verhalten mit dem Bereich, in dem die
myFormName
Variable sichtbar sein$scope
würde, aberundefined
wenn ich versuchte, darauf zuzugreifen. Das hat mich verwirrt.quelle
name="{{name1}}"
ich habe noch keine Antwort darauf gefunden.Ab AngularJS 1.5.0 gibt es dafür eine viel sauberere Lösung (im Gegensatz zur
link
direkten Verwendung der Funktion). Wenn Sie auf ein FormularFormController
im Direktiven-Controller Ihrer Unterkomponente zugreifen möchten , können Sie dasrequire
Attribut einfach wie folgt auf die Direktive schlagen :return { restrict : 'EA', require : { form : '^' }, controller : MyDirectiveController, controllerAs : 'vm', bindToController : true, ... };
Als Nächstes können Sie in Ihrer Vorlage oder in Ihrem Direktiven-Controller wie bei jeder anderen Bereichsvariablen darauf zugreifen, z .
function MyDirectiveController() { var vm = this; console.log('Is the form valid? - %s', vm.form.$valid); }
Beachten Sie, dass für diese Funktion auch das
bindToController: true
Attribut in Ihrer Direktive festgelegt sein muss. Weitere Informationen finden Sie in der Dokumentation zu$compile
und in dieser Frage.Relevante Teile aus der Dokumentation:
quelle
Hat deine Geigenarbeit "Was ich vorziehen würde" gemacht! Aus irgendeinem Grund konnte die Zeichenfolge "$ scope.ngForm" in einem console.log angezeigt werden, aber die direkte Protokollierung funktionierte nicht, was zu undefiniert führte. Sie können es jedoch erhalten, wenn Sie Attribute an die Controller-Funktion übergeben.
app.directive('myForm', function() { return { restrict: 'A', controller: ['$scope','$element','$attrs', function($scope,$element,$attrs) { this.getForm = function() { return $scope[$attrs['ngForm']]; } }] } });
http://jsfiddle.net/vZ6MD/20/
quelle