我有一个简单的输入验证功能。每次用户点击submit
时,都会验证输入。不知何故,$ watch仅在输入无效时第一次起作用,并且在第二次和后续时间不起作用。
代码如下。
<form ng-submit="validateInput(input)">
<input ng-model="input.first">
<input ng-model="input.second">
<input type="submit" value="Submit">
</form>
function validateInput(input) {
$scope.errorMessage = ""; //reset errorMessage to "" for every new submission.
if (condition) {
//http call
} else {
$scope.errorMessage = "Invalid input".
}
}
app.directive('showError', function() {
return {
restrict: 'A',
link: function(_scope, _element) {
_scope.$watch('errorMessage', function(newVal) {
if (newVal) {
$(_element).find("#errorMessage").html(newVal);
$(_element).slideDown().delay(3000).slideUp();
}
});
$(_element).find(".hide-message").on("click", function() {
$(_element).slideUp();
});
}
};
});
showError
指令是页面中面板的属性。当需要显示错误消息时,面板将从显示错误消息的页面顶部向下滑动,然后在3秒后向上滑动。
conditon==false
第一次触发$ watch。但第二次(以及之后的时间),$ watch将不会被触发。
我使用了console.log($scope.errorMessage)
来确保每次提交时,errorMessage
首先设置为""
,然后设置为"Invalid input"
。但该小组将首次下滑,而不是以下时间。
奇怪的是:如果我只是将输入传递给后端进行验证并从后端返回errorMessage
,它总是有效。
(感谢所有的帮助。简短的解决方案:如果$ digest循环被触发,$ watch将起作用。$ http调用将触发$ digest循环。在这种情况下,$ digest循环不会被触发,我必须使用$ apply或$ timeout手动触发它。)
答案 0 :(得分:0)
您在单个$digest
循环中将errorMessage从“无效输入”设置为“”并返回“无效输入”,因此$watch
永远不会触发(因为据他所知,价值从未改变过。)
一个懒惰但可行的解决方案是简单地将errorMessage设置为勾选“无效输入”,因此$watch
有时间注意到某些变化:
function validateInput(input) {
$scope.errorMessage = ""; //reset errorMessage to "" for every new submission.
if (condition) {
//http call
} else {
$timeout(function() {
$scope.errorMessage = "Invalid input";
});
});
}
(一个更好的解决方案可能是使用一个可以直接调用而不是$watch
变量的错误处理程序,但听起来就像船只在那个特定的设计选择上航行......)
答案 1 :(得分:0)
是的,您可以通过手动触发摘要或等待下一个摘要来解决此问题。但不确定为什么要在Angular中构建自己的表单验证。 Angular为开箱即用的表单(验证等)提供了很好的实现。
查看:
<form name="form" novalidate>
Name:
<input type="text" ng-model="formDate.name" name="name" required="" />
<br />
<div ng-show="form.$submitted || form.name.$touched" custom-error>
<div ng-show="form.name.$error.required">Tell us your name.</div>
<div ng-show="form.name.$error.customError">For some reason our name needs to be a number.</div>
</div>
Age:
<input type="number" ng-model="formDate.age" name="age" required="" />
<br />
<div ng-show="form.$submitted || form.name.$touched">
<div ng-show="form.age.$error.required">Tell us your age.</div>
</div>
<br/>
<button type="submit" ng-click="submitForm()">Submit</button>
</form>
控制器:
.controller('MainCtrl', function ($scope) {
$scope.formData = {
name: '',
age: ''
}
$scope.submit = function() {
//http call accessin form data through our $scope model
}
});
此处angular将处理隐藏或显示错误消息和表单错误。 Angular表单创建一个表单控制器,通过此控制器,您可以访问每个表单元素及其错误(即form.name。$ required)。像max,min,length,required等常规验证是开箱即用的,但结合编写自定义验证的能力,它变得非常强大(参见https://docs.angularjs.org/guide/forms#custom-validation)。
自定义验证指令
.directive('customError', function() {
var CUSTOM_ERROR_REGEXP = /^\d+$/;
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.customError = function(modelValue, viewValue) {
if (ctrl.$isEmpty(modelValue)) {
// consider empty models to be valid
return true;
}
if (CUSTOM_ERROR_REGEXP.test(viewValue)) {
// it is valid
return true;
}
// it is invalid
return false;
};
}
};
});
答案 2 :(得分:0)
创建自己的检查最好使用可重用的组件,例如指令use-form-error。
查看jsfiddle的示例。
<form name="ExampleForm">
<label>Password</label>
<input ng-model="password" required />
<br>
<label>Confirm password</label>
<input ng-model="confirmPassword" required />
<div use-form-error="isSame" use-error-expression="password && confirmPassword && password!=confirmPassword" ng-show="ExampleForm.$error.isSame">Passwords Do Not Match!</div>
</form>