问题
I'm having a lot of troubles and I don't understand the behavior of
custom validation or may be I misunderstand something.
The directive trigger once ousite watch and inside invalid and twice inside watch (at least in my test)
My goal would be trigger the extra custom validation after the required
and email rules are valid but it doesn't work at all.
So the code
<!doctype html>
<html data-ng-app="myApp">
<head>
<meta charset="utf-8">
</head>
<body>
<div data-ng-controller="myCtrl">
<form novalidate id="frm-signup" name="addContestantFrm" data-ng-submit="addContestant()">
<div>
<label for="email">Email: *</label>
<input type="email" id="email" name="email" class="input-medium" tabindex="3" title="email" maxlength="255" value="{{contestant.email}}" placeholder="email" data-ng-model="contestant.email" required email-unique />
</div>
<div>
<input type="submit" id="sbmt" name="sbmt" class="input-sbt" data-ng-disabled="!addContestantFrm.$valid" value="Send" />
</div>
</form>
</div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.angularjs.org/1.0.8/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.factory('Contestant',function($http){
return {
checkUniqueEmail : function(email){
return $http.post('./checkemail.php',{email:email});
}
}
});
app.controller('myCtrl',function($scope){
});
app.directive('emailUnique',function(Contestant) {
return {
require: 'ngModel',
link: function(scope, element, attrs,ctrl) {
Contestant.checkUniqueEmail(attrs.emailUnique).success(function (response) {
ctrl.$setValidity('emailUnique', true);
console.log('inside valid');
console.log(attrs.emailUnique);
console.log('end inside valid');
return attrs.emailUnique;
})
.error(function (data) {
console.log('inside invalid');
ctrl.$setValidity('emailUnique', false);
console.log('end inside invalid');
return undefined;
});
scope.$watch(attrs.ngModel, function() {
console.log('I am inside watch');
console.log(ctrl.$error.required);
console.log(ctrl.$error.email);
console.log('end watch');
});
console.log('ouside');
console.log(attrs.emailUnique);
console.log('end ouside');
}
}
});
</script>
</body>
</html>
and the fake check
<?php
$data = file_get_contents("php://input");
$data = json_decode($data,true);
if(isset($data['email'])){
if(empty($data['email'])){
header("HTTP/1.0 404 Not Found");
exit;
}
elseif($data['email'] !== 'admin@goo.com'){
header("HTTP/1.0 404 Not Found");
exit;
}
else{
header("HTTP/1.1 200 OK");
return $data['email'];
exit;
}
}
回答1:
app.directive('emailUnique',function(Contestant) {
return {
require: 'ngModel',
link: function(scope, element, attrs,ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
console.log(ctrl.$error.email);
Contestant.checkUniqueEmail(viewValue).success(function (response) {
ctrl.$setValidity('emailUnique', true);
console.log(viewValue);
return viewValue;
})
.error(function (data) {
ctrl.$setValidity('emailUnique', false);
console.log(viewValue);
return undefined;
});
});
}
}
});
Now it works but I'd like call the xhr only when there is a valid email ctrl.$error.email give me always false :(
回答2:
From AngularJS documentation:
$parsers: Array of functions to execute, as a pipeline, whenever the control reads value from the DOM. Each function is called, in turn, passing the value through to the next. The last return value is used to populate the model. Used to sanitize / convert the value as well as validation. For validation, the parsers should update the validity state using $setValidity(), and return undefined for invalid values.
Based on this, if we add the $parser at the end of the pipe (using ctrl.$parsers.push) then, if the input value is invalid, viewValue parameter will be undefined.
I wrote this example to clarify how parsers works: http://jsfiddle.net/oua78v19/7/ (check console to see how parameter value is changed when it is valid)
Updated code sample:
app.directive('emailUnique',function(Contestant) {
return {
require: 'ngModel',
link: function(scope, element, attrs,ctrl) {
ctrl.$parsers.push(function(viewValue) {
if (viewValue) {
// we have a valid email address
// we can do now an ajax call to see
// if email is already in use
}
});
}
}
来源:https://stackoverflow.com/questions/19015292/angular-custom-validation-unique-email-trigger-once