Подтвердить что ты не робот

Форма перехода к директиве

Я хочу инкапсулировать поля формы в директиве, чтобы я мог просто сделать это:

<div ng-form='myForm'>
  <my-input name='Email' type='email' label='Email Address' placeholder="Enter email" ng-model='model.email' required='false'></my-input>

</div>

Как мне получить доступ к myForm в моей директиве, чтобы я мог выполнять проверки проверки, например. myForm.Email.$valid?

4b9b3361

Ответ 1

Чтобы получить доступ к FormController в директиве:

require: '^form',

Затем он будет доступен в качестве 4-го аргумента для вашей функции ссылок:

link: function(scope, element, attrs, formCtrl) {
    console.log(formCtrl);
}

fiddle

Вам может потребоваться доступ только к NgModelController:

require: 'ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
     console.log(ngModelCtrl);
}

fiddle

Если вам нужен доступ к обоим:

require: ['^form','ngModel'],
link: function(scope, element, attrs, ctrls) {
    console.log(ctrls);
}

fiddle

Ответ 2

Вот полный пример: http://plnkr.co/edit/W1KxuL?p=preview (с использованием Bootstrap 3.1)

Он содержит форму с несколькими входами (имя, адрес электронной почты, возраст и страну). Имя, адрес электронной почты и возраст - это директивы. Страна - это "обычный" вход.

Для каждого ввода отображается справочное сообщение, когда пользователь не вводит правильное значение.

Форма содержит кнопку сохранения, которая отключена, если форма содержит хотя бы одну ошибку.

AngularJS form with directives

Ответ 3

Изменить 2: Я оставлю свой ответ, поскольку это может быть полезно по другим причинам, но другой ответ от Марка Райкока - это то, что я изначально хотел сделать, но не смог работать, По-видимому, родительский контроллер здесь был бы form, а не ngForm.


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

Пример

Здесь работает, упрощенный jsFiddle.

Код

HTML:

<div ng-form="myForm">
    <my-input form="myForm"></my-input>
</div>

Основные части директивы:

app.directive('myInput', function() {
    return {
        scope: {
            form: '='
        },
        link: function(scope, element, attrs) {
            console.log(scope.form);
        }
    };
});

Что происходит

Мы попросили Angular связать значение области, названное в атрибуте form, с нашей изолированной областью, используя '='.

Выполнение этого способа отделяет фактическую форму от директивы ввода.

Примечание.. Я попытался использовать require: "^ngForm", но директива ngForm не определяет контроллер и не может использоваться таким образом (что очень плохо).


Все сказанное, я думаю, что это очень многословный и грязный способ справиться с этим. Возможно, вам лучше добавить новую директиву в элемент формы и использовать require для доступа к этому элементу. Я посмотрю, смогу ли я что-то собрать вместе.

Изменить: использование родительской директивы

ОК, здесь лучшее, что я мог бы выяснить, используя родительскую директиву, я объясню больше через секунду:

Работа jsFiddle с помощью родительской директивы

HTML:

<div ng-app="myApp">
    <div ng-form="theForm">
        <my-form form="theForm">
            <my-input></my-input>
        </my-form>
    </div>
</div>

JS (частичный):

app.directive('myForm', function() {
    return {
        restrict: 'E',
        scope: {
            form: '='
        },
        controller: ['$scope', function($scope) {
            this.getForm = function() {
                return $scope.form;
            }
        }]
    }
});

app.directive('myInput', function() {
    return {
        require: '^myForm',
        link: function(scope, element, attrs, myForm) {
            console.log(myForm.getForm());
        }
    };
});

Сохраняет форму в области родительской директивы (myForm) и позволяет дочерним директивам обращаться к ней, требуя родительскую форму (require: '^myForm'), и доступ к контроллеру директивы в функции связывания (myForm.getForm()).

Преимущества:

  • Вам нужно только идентифицировать форму в одном месте.
  • Вы можете использовать свой родительский контроллер для размещения общего кода

Отрицательных:

  • Вам нужен дополнительный node
  • Вам нужно дважды ввести имя формы

Что бы я предпочел

Я пытался заставить его работать с помощью атрибута в элементе формы. Если это сработало, вам нужно будет добавить директиву к тому же элементу, что и ngForm.

Однако я получал какое-то странное поведение с областью действия, где переменная myFormName была бы видна внутри $scope, но была бы undefined, когда я попытался получить к ней доступ. Это меня смущает.

Ответ 4

Начиная с AngularJS 1.5.0, для этого существует гораздо более чистое решение (в отличие от использования функции link). Если вы хотите получить доступ к форме FormController в вашем контроллере директивы подкомпонента, вы можете просто пощекотать атрибут require в директиве, например:

return {
  restrict : 'EA',
  require : {
    form : '^'
  },
  controller : MyDirectiveController,
  controllerAs : 'vm',
  bindToController : true,
  ...
};

Затем вы сможете получить доступ к нему в своем шаблоне или директивном контроллере, как и любая другая переменная области видимости, например:

function MyDirectiveController() {
  var vm = this;
  console.log('Is the form valid? - %s', vm.form.$valid);
}

Обратите внимание, что для этого вам также необходимо установить атрибут bindToController: true в вашей директиве. Дополнительную информацию см. В документации для $compile и этого вопроса.

Соответствующие части документации:

требуется

Требовать другую директиву и ввести свой контроллер в качестве четвертого аргумента функции связывания. Свойством require может быть строка, массив или объект:

Если свойство require является объектом и bindToController является правдивым, то необходимые контроллеры привязаны к контроллеру, используя ключи свойства require. Если имя требуемого контроллера совпадает с именем локального (ключ), имя может быть опущено. Например, {parentDir: '^parentDir'} эквивалентно {parentDir: '^'}.

Ответ 5

Сделал свою работу "Что бы я предпочел"! По какой-то причине вы можете увидеть строку "$ scope.ngForm" в console.log, но запись в нее напрямую не сработала, в результате получилось undefined. Однако вы можете получить его, если передаете атрибуты функции контроллера.

app.directive('myForm', function() {
return {
    restrict: 'A',
    controller: ['$scope','$element','$attrs', function($scope,$element,$attrs) {
        this.getForm = function() {
            return $scope[$attrs['ngForm']];
        }
    }]
}
});

http://jsfiddle.net/vZ6MD/20/