У меня есть обычно повторно используемый набор входных данных формы, которые повторно используются во всем моем приложении, поэтому я пытаюсь инкапсулировать их в настраиваемую директиву. Я хочу установить ngModel
в своей директиве и разделить ее, чтобы ее можно было редактировать в нескольких разных входных данных (некоторые из них сами являются директивами) в основной директиве.
В то же время мне нужно, чтобы результаты проверки формы передавались по цепочке в родительскую форму, чтобы я мог отображать соответствующие сообщения и стили.
Каков самый простой и идиоматический способ реализовать это?
Эти (упрощенные) шаблоны должны дать вам пример того, что я собираюсь сделать...
Внешний шаблон.html
<form name="outerForm">
<my-directive
ng-model="ctrl.myComplexModel"
name="myDirectiveInstance"
custom-required="ctrl.EnableValidateOne"
toggle-another-validation="ctrl.EnableValidateTwo">
</my-directive>
<div ng-messages="outerForm.myDirectiveInstance.$error">
<ng-message when="customRequired">This is required.</ng-message>
<ng-message when="anotherValidation">This is required.</ng-message>
<ng-message when="innerValidationOne">Something wrong with field 1.</ng-message>
<ng-message when="innerValidationTwo">Something wrong with field 2.</ng-message>
<ng-message when="innerValidationThree">Something wrong with field 3.</ng-message>
<!-- etc... -->
</div>
</form>
myDirectiveTemplate.html
<div ng-form="myDirectiveForm">
<div ng-class="{'has-error': myDirectiveForm.fieldOne.$invalid}">
<ui-select
ng-model="model.fieldOne"
name="fieldOne"
required>
</ui-select>
</div>
<div ng-class="{'has-error': myDirectiveForm.fieldTwo.$invalid}">
<input
type="number"
ng-model="model.fieldTwo"
name="fieldTwo"
ng-pattern="directiveCtrl.someRegEx"
ng-required="directiveCtrl.fieldTwoIsRequired">
</div>
<!-- etc... -->
</div>
На данный момент и myDirectiveForm
, и myDirectiveInstance
публикуют себя как свойства outerForm
FormController
. Я надеюсь сделать эту директиву черным ящиком, поэтому тот факт, что myDirectiveForm
присоединяется непосредственно к outerForm
, беспокоит меня и, кажется, указывает на то, что я делаю что-то неправильно.
Вот как сейчас выглядит мое определение директивы.
myDirective.js
app.directive('myDirective', function() {
return {
restrict: 'E',
template: 'myDirectiveTemplate.html',
controller: 'MyDirectiveCtrl',
scope: {
model: '=ngModel',
customRequired: '=?',
toggleAnotherValidation: '=?'
},
require: 'ngModel',
link: function(scope, iElem, iAttrs, ngModelController) {
// Black-box the internal validators
// Custom validator to avoid conflicts with ngRequired
ngModelController.$validators.customRequired = function(modelValue, viewValue) {
if(!scope.customRequired)
return true;
// On first digest the field isn't registered on the form controller yet
if(angular.isUndefined(scope.myDirectiveForm.fieldOne))
return true;
return !scope.myDirectiveForm.fieldOne.$error.required;
};
ngModelController.$validators.anotherValidation = function(modelValue, viewValue) {
if(!scope.anotherValidation)
return true;
return scope.passesBusinessRule();
};
ngModelController.$validators.innerValidationOne = function(modelValue, viewValue) {
if(!scope.anotherValidation)
return true;
if(angular.isUndefined(scope.myDirectiveForm.fieldTwo))
return true;
return !scope.myDirectiveForm.fieldTwo.$error.pattern;
};
/* etc... */
// Deep-watching model so that validations will trigger on updates of properties
scope.$watch('model', function() {
ngModelController.$validate();
}, true);
}
};
});