我创建了一个'wrapper'指令,该指令用作表单元素包装器。一个或多个输入可以包装在该指令中。
该指令本身包含ng-form
指令,因此我可以检查每个实例是否有错误以及(ng-model)输入是否无效。
在包装模板中,我想在以下情况下添加“错误”类:
一个或多个输入是$ invalid
和:
表格已提交
要么
触摸一个或多个输入
这是我当前的(剥离的)包装器指令:
export class FormElementWrapper {
public transclude = true;
public template = `
<div ng-form="formElementWrapper"
ng-class="{'has-error': showError }" ng-transclude>
</div>
`;
public link = (scope, element, attrs) => {
// custom keep track of touched
var touched = false;
var isSubmitted = function(): boolean {
var form: any = scope.formElementWrapper;
return form.$$parentForm.$submitted;
};
scope.$watch(() => {
// show error when:
// - one ore more inputs are invalid
// - AND
// -- form is touched
// -- OR
// -- parent form is submitted
var submitted = isSubmitted();
return scope.formElementWrapper.$invalid && (touched || submitted);
}, (val) => {
scope.showError = val;
});
// override $setPristine to reset the custom touched property
var origPristine = scope.formElementWrapper.$setPristine;
scope.formElementWrapper.$setPristine = () => {
touched = false;
origPristine();
}
// bind to blur events of all inputs
element.on("blur", ":input", () => {
touched = true;
});
}
}
问题:如何知道一个或多个元素是否被触及? ngFormController没有该属性。当前,我绑定到输入的
blur
事件,但是我可以想象使用ng-model
的其他指令本身不必是输入。 最佳答案
基本上,您可以使用未触及的对数的负数$pristine
。因此,您可以使用if(!form.$pristine)
进行检查,然后表示已触摸表格。
根据form.FormController docs,如果用户尚未与表单交互,则$pristine
为True
。
但是,如果您想将NgModelController.$touched
扩展到FormController,则可以在任何元素模糊时将$touched = true
简单地添加到表单中。这可以通过使用与ngModel
并发的指令来完成,并在元素由FormController.$touched
事件触发时更改其blur
值。
下面的示例实现此解决方案。
angular.module('app', [])
.directive('ngModel', function() {
return {
restrict: 'A',
require: ['^?form'],
priority: 1000,
link: function(scope, elem, attr, ctrls) {
var ngFormCtrl = ctrls[0];
if (ngFormCtrl) {
elem.on('blur', function onBlurEvent() {
scope.$apply(function() {
ngFormCtrl.$touched = true;
elem.off('blur', onBlurEvent);
});
});
}
}
};
})
.controller('myController', function($rootScope) {
var $ctrl = this;
$ctrl.model = {
name: 'lenny',
age: 23
};
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.js"></script>
<div ng-controller="myController as $ctrl">
<form name="$ctrl.myForm" novalidate>
<label>Name :
<input name="test1" ng-model="$ctrl.model.name">
</label>
<label>age :
<input name="test2" ng-model="$ctrl.model.age">
</label>
<label>{{ $ctrl.myForm.$touched ? 'Touched' : 'Untouched'}}</label>
</form>
</div>