AMar4enko
@AMar4enko

Как в AngularJS сделать добавление директив «на лету»?

У меня есть форма, достаточно большая.
Есть уже сработанный механизм по отображению ошибок на форме, он завязан на стандартную AngularJS валидацию + своя директива для отображения ошибок серверной валидации.
Все работает, но есть одно "но" - html-код формы после добавления к элементам всех этих директив становится мусорной кучей. Надо ведь ng-class везде добавить, чтобы элемент формы выделить, да еще бы под него запихать списочек проблем, которые с ним возникли.
Захотелось сделать директиву, которая брала бы данные из объекта в $scope и на основании данных в нем применяла бы нужные директивы элементам формы на лету.
Например:
$scope.formSettings = {
     'required': ['title','description','date_from'],
     'server': ['title','description']
}

Я сделал директиву, которая добавляет ngRequired элементу при линковке, она даже работает. Выглядит как-то так:
return app.directive('formControl', [
    '$compile', '$injector', function($compile, $injector) {
      return {
        priority: 0,
        require: '?ngModel',
        link: function($scope, element, attrs, controller) {
          var required;
          attrs.$set('ngRequired', "" + attrs.formControl + ".required('" + (element.attr('name')) + "')");
          required = $injector.get('requiredDirective')[0];
          return required.link($scope, element, attrs, controller);
        }
      };
    }
  ]);

Дело в том, что в таком варианте не обрабатывается само выражение, заданное для ng-required - элемент всегда считается required.
Как быть? Я даже полистал код AngularJS, нашел объявление директивы, но как там происходит обработка выражения из ngRequired хоть убей - не пойму.
Вижу, что стоит
attr.$observe('required', function() {
        validator(ctrl.$viewValue);
      });

AngularJS 1.2.2
  • Вопрос задан
  • 4288 просмотров
Решения вопроса 1
AMar4enko
@AMar4enko Автор вопроса
Разобрался. Если кому интересно:
Дело было, на самом деле, во внутренностях ангуляра, а точнее в том, что он при компиляции ноды принудительно проверяет наличие некоторых атрибутов, и делает для их содержимого $scope.$watch, внутри которого делает attrs.$set.
Так как я добавлял ngRequired после компиляции ноды, то мне надо было просто сделать что-то типа:
$scope.$watch(attrs.formControl + ".required('" + (element.attr('name')) + "')", function(value){
    attrs.$set("required", !!value)
 });

А ngRequired, как показано выше, отслеживает значение атрибута required и обновляет валидацию.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
EugeneOZ
@EugeneOZ
После изменения состава атрибутов и/или директив, нужно перекомпилировать элемент (вызвать compile над ним).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы