2014-01-09 5 views
0

Я пытаюсь создать некоторые пользовательские проверки для пользовательских компонентов ввода.AngularJS: Контроллер - двунаправленная связь директивы

Директива пользовательского ввода будет действовать как черный ящик, поэтому я могу добавить проверки, которые хочу получить от контроллера.

Для этого я добавить атрибут для директивы, которая называется «валидацией», ре:

<custom-input validations="checkEmail() checkIsNotUsed()" type="text" placeholder="Email"></custom-input> 

В этом примере я могу определить мои валидации от контроллера, как я хочу, с идеей, что когда Я хочу отправить с контроллера, он проверяет, проверен ли этот компонент для «checkEmail()» и «checkIsNotUsed()». Для этого мне понадобится двунаправленная связь между контроллером и внутренней директивой, т. Е. используя адрес электронной почты:

  1. Контроллер хочет проверить компонент, поэтому он вызовет внутреннюю директиву для получения внутреннего элемента ввода.
  2. Директива возвращает входной сигнал на контроллер.
  3. Контроллер может проверять входные данные на основании связанных с ним проверок.

Я пробовал разные подходы, но я не могу получить конечную цель.

Here is the example I've been working with.

EDIT

Решено: http://plnkr.co/edit/DMUVLifuWeGEuXOVfRwE?p=preview

ответ

1

Я бы немного вопрос, нужно ли вам директиву как полный черный ящик. Во-первых, обычно вам понадобятся некоторые сообщения о проверке или некоторая информация, отображаемая пользователю в разных случаях недопустимых данных, поэтому просто неверное/ложное возвращаемое значение любого валидатора недостаточно. Во-вторых, вы также воссоздавать много чего Угловое уже дает вам ngForm, ngModel, ngModelController и директивы input, особенно $setValidity функцию ngModelController

Я бы поставил каждый валидатор в своей директиве, что require s ngModel: один для электронной почты и один для пароля, например. Тем не менее, вы все равно можете передавать параметры от общего контроллера, но каждая директива адаптирована к требуемой информации. Например, validationEmail директива может принять массив существующих писем используется:

<input validation-email validation-email-used="usedEmails" ng-model="data.email" type="text" placeholder="Email" name="email" ng-required /> 

Где usedEmails массив писем.Директива может быть записана в виде:

app.directive('validationEmail', function() { 
    return { 
    require: 'ngModel', 
    scope: { 
     validationEmailUsed:'=' 
    }, 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function(email) { 
     // Test the email and call 
     // ngModelController.$setValidity(...) 
     // to set the validity of the email 
     }); 
    } 
    }; 
}); 

Вы можете увидеть это в действии в modified version of your Plunker

Edit: Если вы хотите интегрировать с серверной стороны проверки, когда все проверки на стороне клиента прошло от директивы, вы можете сделать это из функции передается ngSubmit по форме:

<form name="myForm" ng-submit="submit()"> 

который может быть закодирована с использованием того факта, форма выставляет себя на сфере, и все его ngModel контроллеров (для того же от Например, с помощью $timeout, а не вызывать $http или услугу),

$scope.submit = function() { 
$timeout(function() { 
    $scope.myForm.username.$setValidity('available',false); 
    $scope.myForm.email.$setValidity('emailFree',false); 
    },500); 
} 

проблема с этим является то, что вы тогда могли бы хотеть, чтобы отметить вход в силу после того, как пользователь изменил его. Вы можете создать validOnChange директиву, которая будет использоваться в качестве:

<input ng-model="data.username" type="text" placeholder="Username" name="username" valid-on-change="available" ng-required /> 

и кодируются в качестве:

app.directive('validOnChange', function() { 
    return { 
    require: 'ngModel', 
    scope: '', 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function() { 
     ngModelController.$setValidity(attributes.validOnChange,true); 
     }); 
    } 
    } 
}); 

see this in this Plunker Вы можете.

Другим общим преимуществом работы с ngForm и ngModelController является то, что он добавляет много классов в форму и элемент в зависимости от состояния ошибки/допустимого ввода и предоставляет состояние ошибки в области, поэтому вы можете показать/скрыть сообщения об ошибках, используя ngIf, например.

+0

Это хорошо, но я все еще чувствую, что не хочу проверять, пока не нажму кнопку «Отправить». С точки зрения масштабируемости этот подход недостаточно хорош, представьте, что завтра я хочу проверить с моим бэкэнд, если поля действительны, я не буду проверять каждый раз, когда я набираю, но когда я нажимаю кнопку submit. Итак, мой вопрос: с помощью Angular можно инициировать это действие, когда вы нажимаете кнопку «Отправить»? – DreaMTT

+0

Кроме того, используя ваше решение, я не могу использовать директиву для настройки входных данных, которые мне понадобятся. Я попытался отредактировать ваш plunkr, используя вложенные директивы, но каким-то образом я не могу передать внутренний ввод с проверками. Если вы можете проверить это и пролить немного, я буду очень признателен за это: http: //plnkr.co/edit/DB0a3rjaRhKk7NV4dt5v? P = preview Большое спасибо за вашу помощь! – DreaMTT

+0

@DreaMTT Я изменил свой ответ, показывая, как вы все еще можете установить срок действия после того, как форма прошла проверку на стороне клиента из директив и была отправлена ​​на сервер. –

Смежные вопросы