Passwort-Check-Direktive in anglejs


76

Ich schreibe eine Anweisung zur Kennwortüberprüfung:

 Directives.directive("passwordVerify",function(){
    return {
        require:"ngModel",
        link: function(scope,element,attrs,ctrl){
            ctrl.$parsers.unshift(function(viewValue){
                var origin = scope.$eval(attrs["passwordVerify"]);
                if(origin!==viewValue){
                    ctrl.$setValidity("passwordVerify",false);
                    return undefined;
                }else{
                    ctrl.$setValidity("passwordVerify",true);
                    return viewValue;
                }
            });

        }
    };
});

html:

<input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
<input data-ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">

Wenn bei zwei Kennwortfeldern in einem Formular beide Kennwortwerte gleich sind, ist das von der Anweisung betroffene Feld gültig. Das Problem ist, dass es in eine Richtung funktioniert (dh wenn ich ein Passwort in das Feld zur Passwortüberprüfung eingebe). Wenn jedoch das ursprüngliche Kennwortfeld aktualisiert wird, wird die Kennwortüberprüfung nicht gültig.

Irgendeine Idee, wie ich eine "Zwei-Wege-Bindungsüberprüfung" durchführen lassen könnte?

Antworten:


60

Dies sollte es lösen:

Aussicht:

<div ng-controller='Ctrl'>
   <form name='form'>
      <input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
      <div ng-show="form.password.$error.required">
        Field required</div>
      <input ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">
      <div ng-show="form.confirm_password.$error.required">
        Field required!</div>
      <div ng-show="form.confirm_password.$error.passwordVerify">
        Fields are not equal!</div>
   </form
</div>

Richtlinie

var app = angular.module('myApp', []);

app.directive("passwordVerify", function() {
   return {
      require: "ngModel",
      scope: {
        passwordVerify: '='
      },
      link: function(scope, element, attrs, ctrl) {
        scope.$watch(function() {
            var combined;

            if (scope.passwordVerify || ctrl.$viewValue) {
               combined = scope.passwordVerify + '_' + ctrl.$viewValue; 
            }                    
            return combined;
        }, function(value) {
            if (value) {
                ctrl.$parsers.unshift(function(viewValue) {
                    var origin = scope.passwordVerify;
                    if (origin !== viewValue) {
                        ctrl.$setValidity("passwordVerify", false);
                        return undefined;
                    } else {
                        ctrl.$setValidity("passwordVerify", true);
                        return viewValue;
                    }
                });
            }
        });
     }
   };
});

1
Ich habe das Validierungs-Snippet im Dokument verwendet. Lassen Sie mich Ihren Code ausprobieren.
mpm

Ich habe meine Antwort geändert. Das sollte funktionieren. Siehe jsFiddle
asgoth

Dies gibt immer noch keine 2-Wege-Bindungen, oder hat sich seitdem etwas geändert?
Hadesara

1
Ich stimme CWSpear zu. Die Lösung sollte mit dem oben kommentierten Fehler korrigiert werden
gyss

9
Bei dieser Lösung liegt ein Speicherverlust vor. Jedes Überwachungsereignis, das ausgelöst wird, schiebt einen anderen Parser auf das Array ctrl. $ Parsers. Wenn Sie Strg. $ Parsers.length am Ende des Watch-Event-Handlers überprüfen, wird dies angezeigt.
mshiltonj

114

Ich verwende die folgende Anweisung, weil ich beide Eingabefelder erneut validieren möchte, unabhängig davon, ob Wert 1 oder Wert 2 geändert wurde:

Richtlinie:

'use strict';

angular.module('myApp').directive('equals', function() {
  return {
    restrict: 'A', // only activate on element attribute
    require: '?ngModel', // get a hold of NgModelController
    link: function(scope, elem, attrs, ngModel) {
      if(!ngModel) return; // do nothing if no ng-model

      // watch own value and re-validate on change
      scope.$watch(attrs.ngModel, function() {
        validate();
      });

      // observe the other value and re-validate on change
      attrs.$observe('equals', function (val) {
        validate();
      });

      var validate = function() {
        // values
        var val1 = ngModel.$viewValue;
        var val2 = attrs.equals;

        // set validity
        ngModel.$setValidity('equals', ! val1 || ! val2 || val1 === val2);
      };
    }
  }
});

Verwendung

<input type="password" ng-model="value1" equals="{{value2}}" required>
<input type="password" ng-model="value2" equals="{{value1}}" required>

4
Ich fand das ganz gut. Eine Sache, die mich überrascht hat, ist, dass wenn Sie einen anderen Winkelprüfer haben wie: ng-minlengthauf dem ersten Feld, dann wird dieses Modell nicht gesetzt, bis es tatsächlich gültig ist
Intellix

5
Ich wickelte ngModel.$setValiditymit if (val1 && val2) { .. }gerade so das Formular nicht ungültig ist , wenn beide Werte leer sind.
Jesus

4
Dies hat einige kleine Probleme, wenn mehr Validierungsregeln im Spiel sind. Wenn eine andere Validierung fehlschlägt, aktualisiert Angular das Modell nicht und im Vergleich passieren seltsame
Dinge

7
Das hat bei mir super funktioniert. Als Neuling wäre es hilfreich, die Validierungszeichenfolge hinzuzufügen. [form name].[field name].$error.equalsVerwenden Sie diese Option, um zu steuern, welche Felder angezeigt werden sollen oder sollen. Ich benutze es für Fehlerbezeichnungen.
Metric152

3
Ich denke , dass es besser ist , zu ersetzen , ngModel.$setValidity('equals', val1 === val2);mitngModel.$setValidity('equals', ! val1 || ! val2 || val1 === val2);
bullgare

85

Das Erstellen einer separaten Direktive hierfür ist nicht erforderlich. Das Tool zur Überprüfung des Angular UI-Kennworts ist bereits integriert . Damit könnten Sie tun:

<input name="password" required ng-model="password">
<input name="confirm_password"
       ui-validate=" '$value==password' "
       ui-validate-watch=" 'password' ">

 Passwords match? {{!!form.confirm_password.$error.validator}}

3
das erfordert derzeit jQuery
Intellix

24
@ DominicWatson Wofür stimmst du mich ab? Diese Frage handelt von eckigen und ich beziehe mich auf die eckigen Dokumente. Lerne es, wenn du den Unterschied zwischen ihnen nicht verstehst.
Fahrrad

24
@DominicWatson Die Direktive ist hier github.com/angular-ui/ui-utils/blob/master/modules/validate/… außer von jquery lite gibt es keine verdammte jquery darin. Wenn Sie so anti-jquery sind, sollten Sie dieses Framework sowieso nicht verwenden, da es jquery enthält.
Fahrrad

3
Ich habe das gleiche Problem wie der ursprüngliche Beitrag. Wenn in Angular-UI bereits etwas eingebaut ist, ist es dann nicht sinnvoll, es zu verwenden, anstatt das Rad neu zu erfinden?
PeterG

2
@ PeterG Ich glaube nicht, dass Dominic Watson eine Ahnung hatte, wovon er sprach
Fahrrad

22

Eine weitere Möglichkeit besteht darin, das Modell einer Eingabe an den Wert einer anderen Eingabe anzupassen.

app.directive('nxEqual', function() {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, model) {
            if (!attrs.nxEqual) {
                console.error('nxEqual expects a model as an argument!');
                return;
            }
            scope.$watch(attrs.nxEqual, function (value) {
                model.$setValidity('nxEqual', value === model.$viewValue);
            });
            model.$parsers.push(function (value) {
                var isValid = value === scope.$eval(attrs.nxEqual);
                model.$setValidity('nxEqual', isValid);
                return isValid ? value : undefined;
            });
        }
    };
});

Wenn es sich also um das Modell der Kennwortbox handelt login.password, legen Sie das folgende Attribut in der Bestätigungsbox fest: nx-equal="login.password"und testen auf formName.elemName.$error.nxEqual. Wie so:

<form name="form">
    <input type="password" ng-model="login.password">
    <input type="password" ng-model="login.verify" nx-equal="login.password" name="verify">
    <span ng-show="form.verify.$error.nxEqual">Must be equal!</span>
</form>

Erweiterte Version:

Für ein neues Projekt von mir musste ich die obige Direktive so ändern, dass der nxEqualFehler nur angezeigt wird, wenn und nur wenn die Überprüfungseingabe einen Wert hat. Andernfalls sollte der nxEqualFehler stummgeschaltet werden. Hier ist die erweiterte Version:

app.directive('nxEqualEx', function() {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, model) {
            if (!attrs.nxEqualEx) {
                console.error('nxEqualEx expects a model as an argument!');
                return;
            }
            scope.$watch(attrs.nxEqualEx, function (value) {
                // Only compare values if the second ctrl has a value.
                if (model.$viewValue !== undefined && model.$viewValue !== '') {
                    model.$setValidity('nxEqualEx', value === model.$viewValue);
                }
            });
            model.$parsers.push(function (value) {
                // Mute the nxEqual error if the second ctrl is empty.
                if (value === undefined || value === '') {
                    model.$setValidity('nxEqualEx', true);
                    return value;
                }
                var isValid = value === scope.$eval(attrs.nxEqualEx);
                model.$setValidity('nxEqualEx', isValid);
                return isValid ? value : undefined;
            });
        }
    };
});

Und du würdest es so benutzen:

<form name="form">
    <input type="password" ng-model="login.password">
    <input type="password" ng-model="login.verify" nx-equal-ex="login.password" name="verify">
    <span ng-show="form.verify.$error.nxEqualEx">Must be equal!</span>
</form>

Probieren Sie es aus: http://jsfiddle.net/gUSZS/


3
Dieser ist der beste. Es ist am prägnantesten. Es funktioniert mit Modellwerten und in beide Richtungen.
CMCDragonkai

Eine Sache ist jedoch, dass die $ parser-Pipe den Wert oder undefiniert zurückgeben sollte. Auf diese Weise enden nachfolgende Pipes nicht nur, weil sie immer undefiniert zurückgegeben werden, wenn keine Rückgabefunktion vorhanden ist. Auch der Umfang sollte falsch sein.
CMCDragonkai

@CMCDragonkai: Guter Fang! Ich habe den Rückgabewert der Parser-Funktion aktualisiert. Soweit ich weiß, wird der Geltungsbereich standardmäßig verwendet false, indem ein Geltungsbereich nicht explizit angegeben wird scope: false.
Fredric

Ich denke, es ist standardmäßig wahr, ein untergeordnetes Ziel zu sein. Aber ich habe in letzter Zeit nicht nachgesehen.
CMCDragonkai

1
@GillBates Wenn Sie einen isolierten Bereich verwenden und das Argument durch binden, =wird die erste Eingabe nach dem Ausfüllen nicht erneut überprüft. Ich habe eine schnelle JSFiddle erstellt , die dieses Problem anzeigt.
Fredric

14

Ich habe es ohne Anweisung getan.

<input type="password" ng-model="user.password" name="uPassword" required placeholder='Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
    <span class="error" ng-show="form.uPassword.$dirty && form.uPassword.$error.minlength">Too short</span>
    <span ng-show="form.uPassword.$dirty && form.uPassword.$error.required">Password required.</span><br />

    <input type="password" ng-model="user.confirmpassword" name="ucPassword" required placeholder='Confirm Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
    <span class="error" ng-show="form.ucPassword.$dirty && form.ucPassword.$error.minlength">Too short</span>
    <span ng-show="form.ucPassword.$dirty && form.ucPassword.$error.required">Retype password.</span>
    <div ng-show="(form.uPassword.$dirty && form.ucPassword.$dirty) && (user.password != user.confirmpassword)">
        <span>Password mismatched</span>
    </div>

4
Sie sollten eine Anweisung verwenden, wie bereits erwähnt, das Formular bleibt in einem gültigen Zustand. Andernfalls hätten Sie auch einen JQuery-Listener dafür machen können.
Fahrrad


8

Ab Winkel 1.3.0-beta12 schreiben ungültige Eingaben nicht in ngModel, sodass Sie nicht sehen UND DANN validieren können, wie Sie hier sehen können: http://plnkr.co/edit/W6AFHF308nyKVMQ9vomw?p=preview . Eine neue Validator-Pipeline wurde eingeführt, an die Sie anhängen können, um dasselbe zu erreichen.

In diesem Sinne habe ich eine Bower-Komponente für gängige zusätzliche Validatoren erstellt: https://github.com/intellix/angular-validators, die dies enthält.

angular.module('validators').directive('equals', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attrs, ngModel)
        {
            if (!ngModel) return;

            attrs.$observe('equals', function() {
                ngModel.$validate();
            });

            ngModel.$validators.equals = function(value) {
                return value === attrs.equals;
            };
        }
    };
});

angular.module('validators').directive('notEquals', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attrs, ngModel)
        {
            if (!ngModel) return;

            attrs.$observe('notEquals', function() {
                ngModel.$validate();
            });

            ngModel.$validators.notEquals = function(value) {
                return value === attrs.notEquals;
            };
        }
    };
});

beste Lösung bisher denke ich
Rathma

7

Ich habe diese Richtlinie bereits mit Erfolg angewendet:

 .directive('sameAs', function() {
  return {
    require: 'ngModel',
    link: function(scope, elm, attrs, ctrl) {
      ctrl.$parsers.unshift(function(viewValue) {
        if (viewValue === scope[attrs.sameAs]) {
          ctrl.$setValidity('sameAs', true);
          return viewValue;
        } else {
          ctrl.$setValidity('sameAs', false);
          return undefined;
        }
      });
    }
  };
});

Verwendung

     <input ... name="password" />
    <input type="password" placeholder="Confirm Password" 
name="password2" ng-model="password2" ng-minlength="9" same-as='password' required>

Ich mag diese Lösung am besten - beschränkt sie nicht auf Passwortübereinstimmung
Shaz

7

Ich habe mich mit dem gleichen Thema befasst und einen guten Blog-Beitrag darüber gefunden, der von Piotr Buda geschrieben wurde. Es ist eine gute Lektüre und erklärt den Prozess sehr gut. Der Code lautet wie folgt:

directives.directive("repeatPassword", function() {
    return {
        require: "ngModel",
        link: function(scope, elem, attrs, ctrl) {
            var otherInput = elem.inheritedData("$formController")[attrs.repeatPassword];

            ctrl.$parsers.push(function(value) {
                if(value === otherInput.$viewValue) {
                    ctrl.$setValidity("repeat", true);
                    return value;
                }
                ctrl.$setValidity("repeat", false);
            });

            otherInput.$parsers.push(function(value) {
                ctrl.$setValidity("repeat", value === ctrl.$viewValue);
                return value;
            });
        }
    };
});

Sie könnten also so etwas tun:

<input type="password" name="repeatPassword" id="repeatPassword" placeholder="repeat password" ng-model="user.repeatPassword" repeat-password="password" required>

Gutschrift geht an den Autor


Nach einer Menge Durcheinander war dies die beste Lösung für mich, wenn ich zusätzliche Validierungsattribute verwendete (z. B. Mindestlänge, erforderlich usw.)
Carlos P

3

Ist das nicht gut genug:

<input type="password" ng-model="passwd1" />
<input type="password" ng-model="passwd2" />
<label ng-show="passwd1 != passwd2">Passwords do not match...</label>
<button ng-disabled="passwd1 != passwd2">Save</button>

Einfach und funktioniert gut für mich.


1
Dies ist keine Validierung. form. $ valid wird gleich true sein.
Intellix

Wir könnten die Schaltfläche Speichern deaktivieren, bis die Passwortbedingung erfüllt ist (dasselbe oben hinzugefügt).
Jasper

Dies ist immer noch keine ordnungsgemäße Validierung. Es gibt ein ganzes Validierungssystem, es ist einfach albern, es nicht zum Speichern einiger Zeilen zu verwenden.
DennisK

Dennis Kr0ger> Es funktioniert gut. Könnten Sie bitte darauf hinweisen, was daran falsch ist?
Jasper

3

Diese Lösung ähnelt der von Dominic Watson, der $ validators verwendet und die mir am besten gefällt. Die einzigen Änderungen sind, dass Sie einen Ausdruck sehen können.

$ validators Eine Sammlung von Validatoren, die angewendet werden, wenn sich der Modellwert ändert. Der Schlüsselwert innerhalb des Objekts bezieht sich auf den Namen des Validators, während sich die Funktion auf die Validierungsoperation bezieht. Die Validierungsoperation wird mit dem Modellwert als Argument bereitgestellt und muss abhängig von der Antwort dieser Validierung einen wahren oder falschen Wert zurückgeben

von https://code.angularjs.org/1.3.15/docs/api/ng/type/ngModel.NgModelController

Ich benutze Winkel 1.3. Meine Richtlinie sieht ungefähr so ​​aus

angular.module('app').directive("passwordConfirm", function() {
    "use strict";
    return {
        require : "ngModel",
        restrict : "A",
        scope : {
            //We will be checking that our input is equals to this expression
            passwordConfirm : '&'
        },
        link : function(scope, element, attrs, ctrl) {
            //The actual validation
            function passwordConfirmValidator(modelValue, viewValue) {
                return modelValue == scope.passwordConfirm();
            }
            //Register the validaton when this input changes
            ctrl.$validators.passwordConfirm = passwordConfirmValidator;
            //Also validate when the expression changes
            scope.$watch(scope.passwordConfirm, ctrl.$validate);
        }
    };
});

Um es zu benutzen

<input type="password" ng-model="user.password"/>
<input type="password" ng-model="user.confirmPassword" 
                password-confirm="user.password" />

3

Um die Form mit zwei Eingabefeldern zu validieren, finde ich den am besten geeigneten Weg

Richtlinie

app.directive('passwordVerify', function() {
return {
    require: 'ngModel',
    link: function (scope, elem, attrs, ctrl) {
        if (!attrs.passwordVerify) {
            return;
        }
        scope.$watch(attrs.passwordVerify, function (value) {
          if( value === ctrl.$viewValue && value !== undefined) {
             ctrl.$setValidity('passwordVerify', true);
             ctrl.$setValidity("parse",undefined);
          }
          else {
             ctrl.$setValidity('passwordVerify', false);
          }
        });
        ctrl.$parsers.push(function (value) {
            var isValid = value === scope.$eval(attrs.passwordVerify);
            ctrl.$setValidity('passwordVerify', isValid);
            return isValid ? value : undefined;
        });
    }
  };
});

HTML

     <div class="row">
        <div class="col-md-10 col-md-offset-1">
          <div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required || (form.password.$error.minlength || form.password.$error.maxlength)}">
              <input type="password" name="password" ng-minlength="6" ng-maxlength="16" id="password" class="form-control" placeholder="Password" ng-model="user.password" required />
              <span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
              <span ng-show="form.password.$error.minlength || form.password.$error.maxlength" class="help-block">Password must be 6-16 character long</span>
          </div>
        </div>
       </div>
       <div class="row">
         <div class="col-md-10 col-md-offset-1">
           <div class="form-group" ng-class="{ 'has-error': (form.confirm_password.$dirty && form.confirm_password.$error.required) || form.confirm_password.$error.passwordVerify }">
              <input type="password" name="confirm_password" id="confirm_password" class="form-control" placeholder="Confirm Password" ng-model="user.confirm_password" required password-verify="user.password" />
              <span ng-show="form.confirm_password.$dirty && form.confirm_password.$error.required" class="help-block">Confirm Password is required</span>
              <span ng-show="form.confirm_password.$error.passwordVerify" class="help-block">Please make sure passwords match & must be 6-16 character long</span>
          </div>
        </div>
      </div>

2

Dies funktioniert in beide Richtungen und ist einfach und sauber

JavaScript

var app = angular.module("app");

app.controller("SamePaswordController", function () {

  this.password;
  this.confirm;

  this.save = function () {
    alert("Saved!");
  };
}


app.directive("match", function () {
  return {
    restrict:"A",
    require:"ngModel",

    link: function(scope, element, attrs, ctrl) {

      function matchValidator(value) {      

        scope.$watch(attrs.match, function(newValue, oldValue) {

          var isValid = value === scope.$eval(attrs.match);                    
          ctrl.$setValidity('match', isValid);

        });

        return value;
      }

      ctrl.$parsers.push(matchValidator);
    }
  };
});

HTML: Beachten Sie die Match-Direktive

<form name="regForm" ng-controller="SamePaswordController as regCtrl"
      ng-submit="regForm.$valid && regCtrl.save()" novalidate>

  <input name="password" ng-model="regCtrl.password" 
         type="password" required placeholder="Password"/>                

  <input name="confirm" ng-model="regCtrl.confirm" match="regCtrl.password"
         type="password" required placeholder="Confirm password"/>


  <div> regForm is valid:{{regForm.$valid}}</div>

  <input type="submit" value="Save"/>

</form>

Sie können das Repo mit diesem Beispiel https://github.com/rogithub/roangularjs klonen


Die schönen Teile sind: scope. $ Watch, scope. $ Eval und match = "regCtrl.password".
Ro.

Das hat bei mir nicht funktioniert. Uhren auf der Bestätigung auf Änderungen und das Beispiel, das ich glaube, ist falsch. match = {{regCtrl.password "}}
Enkode

2

Keine Richtlinienlösung, funktioniert aber für mich:

<input ng-model='user.password'
 type="password"
 name='password'
 placeholder='password'
 required>
<input ng-model='user.password_verify'
 type="password" 
 name='confirm_password'
 placeholder='confirm password'
 ng-pattern="getPattern()"
 required>

Und in der Steuerung:

//Escape the special chars
    $scope.getPattern = function(){
        return $scope.user.password && 
              $scope.user.password.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1');
    }

http://plnkr.co/edit/QDTnipCsHdg56vgygsqC?p=preview


1

Das Folgende ist meine Sicht auf das Problem. Diese Direktive würde mit einem Formularwert anstelle des Gültigkeitsbereichs verglichen.

'use strict';
(function () {
    angular.module('....').directive('equals', function ($timeout) {
        return {
            restrict: 'A',
            require: ['^form', 'ngModel'],
            scope: false,
            link: function ($scope, elem, attrs, controllers) {
                var validationKey = 'equals';
                var form = controllers[0];
                var ngModel = controllers[1];

                if (!ngModel) {
                    return;
                }

                //run after view has rendered
                $timeout(function(){
                    $scope.$watch(attrs.ngModel, validate);

                    $scope.$watch(form[attrs.equals], validate);
                }, 0);

                var validate = function () {
                    var value1 = ngModel.$viewValue;
                    var value2 = form[attrs.equals].$viewValue;
                    var validity = !value1 || !value2 || value1 === value2;
                    ngModel.$setValidity(validationKey, validity);
                    form[attrs.equals].$setValidity(validationKey,validity);
                };
            }
        };
    });
})();

im HTML bezieht man sich jetzt auf das tatsächliche Formular anstelle des Bereichswerts:

<form name="myForm">
  <input type="text" name="value1" equals="value2">
  <input type="text" name="value2" equals="value1">
  <div ng-show="myForm.$invalid">The form is invalid!</div>
</form>

Sieht nicht so aus, als könnten Formularwerte beobachtet werden, also denke ich, dass $scope.$watch(form[attrs.equals], validate);das eigentlich nie aufgerufen wird. Andernfalls würde es ausreichen, nur ein equalsAttribut für nur ein Element zu haben.
Vadym

0

Um eine Validierung zu erreichen, wenn sich beide Eingaben ändern, verwende ich den folgenden Code (der eine Kombination aller anderen anderen Antworten war):

angular.module('app.directives')
.directive('passwordVerify', [function () {
    return {
        require: '?ngModel',
        restrict: 'A',
        scope: {
            origin: '=passwordVerify'
        },
        link: function (scope, element, attrs, ctrl) {
            if(!ctrl) {
                return;
            }

            function validate(value) {
                ctrl.$setValidity('passwordMatch', scope.origin === value);
                return value;
            }

            ctrl.$parsers.unshift(validate);

            scope.$watch('origin', function(value) {
                validate(ctrl.$viewValue);
            });
        }
    };
}]);

0

Zunächst möchte ich Fredric für die Veröffentlichung dieses hervorragenden Beispiels danken. Es gibt ein kleines Problem, auf das ich zufällig gestoßen bin. auf der Geige, die Sie gepostet haben http://jsfiddle.net/gUSZS/

Wenn Sie ein Kennwort eingeben und dann dasselbe Kennwort im Überprüfungs-Eingabeelement eingeben, funktioniert alles einwandfrei. Versuchen Sie jedoch, dem zweiten Feld ein Leerzeichen hinzuzufügen, und Angular schneidet dieses Leerzeichen automatisch ab. Dies bedeutet, dass die Direktive den zusätzlichen Speicherplatz nicht "sieht". Jetzt sind die Passwörter unterschiedlich, aber das Formular ist noch gültig.

Um dies zu beheben, müssen wir hinzufügen

ng-trim="false"

zu den Eingabeelementen. Dies funktioniert in Angular 1.0.3 nicht. Wenn Sie es in dieser Geige ausprobieren möchten, müssen Sie der Geige 1.1.1 hinzufügen ( http://ajax.googleapis.com/ajax/libs/angularjs/1.1.1/angular) .js )

Aber nochmals, danke Frederic, ich werde Ihre Lösung in meiner App verwenden!

Anton PS Ich wollte Frederics Beitrag kommentieren, aber ich bin neu in diesem Forum und scheine nicht genug Anerkennung zu haben. Es wäre also sehr dankbar, wenn einige von Ihnen meinen Kommentar abstimmen könnten, wenn es Ihnen gefällt :-)


0

Keine Notwendigkeit für eine zusätzliche Richtlinie, hier ist meine Meinung dazu:

HTML:

<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd.$valid }">
    <input type="password" name="new_passwd" class="form-control" data-ng-model="data.new_passwd" placeholder="New Password" required data-ng-pattern="passwdRegex">
    <small class="help-block" data-ng-show="submitted && form.new_passwd.$error.required">New password is required!</small>
    <small class="help-block" data-ng-show="submitted && !form.new_passwd.$error.required && form.new_passwd.$error.pattern">New password is not strong enough!</small>
</div>

<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd_conf.$valid }">
    <input type="password" name="new_passwd_conf" class="form-control" data-ng-model="data.new_passwd_conf" placeholder="Confirm New Password" required data-ng-pattern="passwdConfRegex">
    <small class="help-block" data-ng-show="submitted && form.new_passwd_conf.$error.required">New password confirmation is required!</small>
    <small class="help-block" data-ng-show="submitted && !form.new_passwd_conf.$error.required && form.new_passwd_conf.$error.pattern">New password confirmation does not match!</small>
</div>

Javascript:

$scope.passwdRegex = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$/;
$scope.$watch('data.new_passwd', function() {
    $scope.passwdConfRegex = new RegExp(Regex.escape($scope.data.new_passwd));
});

wo Regex.escape () gefunden werden hier .

Klappt wunderbar!


Ich habe es mit jsfiddle versucht funktioniert nicht, kannst du es zusammenstellen und uns zeigen?
Nick Kahn

0

Um die große Anzahl bereits vorhandener Lösungen zu ergänzen, funktioniert dies gut für mich.

( Die Antwort von Jan Laussmann funktioniert nicht mehr mit den neuesten Beta-Versionen von AngularJS).

Richtlinie:

angular.module('myApp').directive('matchValidator', [function() {
        return {
            require: 'ngModel',
            link: function(scope, elm, attr, ctrl) {
                var pwdWidget = elm.inheritedData('$formController')[attr.matchValidator];

                ctrl.$parsers.push(function(value) {
                    if (value === pwdWidget.$viewValue) {
                        ctrl.$setValidity('match', true); 
                        return value;
                    }                       

                    if (value && pwdWidget.$viewValue) {
                        ctrl.$setValidity('match', false);
                    }

                });

                pwdWidget.$parsers.push(function(value) {
                    if (value && ctrl.$viewValue) {
                        ctrl.$setValidity('match', value === ctrl.$viewValue);
                    }
                    return value;
                });
            }
        };
    }])

Verwendung

<input type="email" ng-model="value1" name="email" required>
<input type="email" ng-model="value2" name="emailConfirm" match-validator="email" required>

Anzeigefehler

<div ng-if="[[yourFormName]].emailConfirm.$error">
    <div ng-if="[[yourFormName]].emailConfirm.$error.match">
        Email addresses don't match.
    </div>
</div>

0
   <input name="password" type="text" required="" ng-model="password" placeholder="password" class="ng-dirty ng-valid ng-valid-required">
   <input name="confirm_password" type="text" required="" ng-model="confirm_password" ui-validate=" '$value==password' " ui-validate-watch=" 'password' " placeholder="confirm password" class="ng-dirty ng-valid-required ng-invalid ng-invalid-validator"> 
   <span ng-show="form.confirm_password.$error.validator">Passwords do not match!</span>
        password errors: {
        "required": false,
        "validator": true
        }

0

Das hat bei mir funktioniert.

Richtlinie:

modulename.directive('passwordCheck', function () {

    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            var Value = null;

            // watch own value and re-validate on change
            scope.$watch(attrs.ngModel, function (val) {
                Value = val;


                validate();
            });

            // observe the other value and re-validate on change
            attrs.$observe('passwordCheck', function () {
                validate();
            });

            var validate = function () {

                // values
                var val1 = Value;
                var val2 = attrs.passwordCheck;

                // set validity

                if (val1 != '' && val1 != undefined) {
                    ngModel.$setValidity('passwordCheck', val1 == val2);

                }

                else {
                    ngModel.$setValidity('passwordCheck', true);
                }
            };
        }
    }
});

HTML:

ng-model="confirmpassword.selected" type="password" name="confirmpassword" 

password-check="{{password.selected}}"

ng-show="resetpasswordform.confirmpassword.$error.passwordCheck && submitted" Password does not match

0

Ich hatte das gleiche Problem, als ich versuchte, meine eigene Direktive zu erstellen, und ich habe es mit diesem Add behoben

ctrl.$validate();

Dabei ist Strg mein ngModelController

Das ist meine Ansicht

<input type="password" match="signupCtrl.registrationData.password" name="confirmPassword" class="form-control" placeholder="Confirm Password" data-ng-model="signupCtrl.registrationData.confirmPassword" required>
        <span ng-messages="registerForm.confirmPassword.$error">
            <span ng-message="match">The Password must match</span>
        </span>

Das ist meine Anweisung

(function () {
    'use strict';
    angular.module('matchDirective', [
        // Angular modules
        // Custom modules
        // 3rd Party Modules
    ]);
})(); 
(function () {
    'use strict';
    angular
        .module('matchDirective')
        .directive('match', match);
    match.$inject = ['$window'];

    function match($window) {
        // Usage:
        //     <element match="source"></element>
        // Creates:
        //
        var directive = {
            link: link,
            restrict: 'A',
            require: 'ngModel',
        };
        return directive;

        function link(scope, element, attrs, ctrl) {
            scope.$watch(attrs['match'], function (newVal, oldVal) {
                ctrl.$validators.match = function (modelValue, viewValue) {
                    if (newVal == modelValue) {
                        return true;
                    } else {
                        return false;
                    }
                }
                ctrl.$validate();
            });
        }
    }
})();

0

So etwas funktioniert bei mir:

js:

.directive('sameAs', function() { return {
    require : 'ngModel',
    link : function(scope, elm, attrs, ngModelCtrl) {

        ngModelCtrl.$validators.sameAs = function(modelValue, viewValue) {
            var checkedVal = attrs.sameAs;
            var thisInputVal = viewValue;

            if (thisInputVal == checkedVal) {
                return true; // valid
            } else {
                return false;
            }
        };
    }
}; });

html:

<input type="password" name="password" id="password" ng-model="password" />

<input type="password" name="passwordRepeat" id="passwordRepeat" 
    ng-model="passwordRepeat" same-as="{{password}}" />

0

Das KISS-Prinzip (Keep It Simple And Stupid) könnte in diesem Fall nützlich sein. Es ist schneller und einfacher zu überprüfen, ob beide Passwörter übereinstimmen, indem Sie folgende Schritte ausführen:

<div ng-app="app" ng-controller="passwordCheck">
  <form name="signUp" ng-submit="submitForm()" novalidate>
     <input type="password" name="password" ng-model="password" required>
     <input type="password" name="ConfirmPassword" ng-model="passwordconfirm"   required>
     <button type="submit"> Submit</button>
  </form>

  <hr>
  <span>Do they match?</span> {{signUp.password.$viewValue == signUp.confirmPassword.$viewValue}}
    </div>

Und bevor Sie das Formular abschicken, können Sie dies in Ihrem js tun

var app = angular.module("app", []);
app.controller("passwordCheck", function($scope) {
   $scope.submitForm = function() {
      if ($scope.signUp.$valid && $scope.signUp.password.$viewValue == $scope.signUp.confirmPassword.$viewValue) {
            alert('Its a match!');
        };
};
});

Sie können es auch in JSfiddle testen .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.