У нас есть контактная форма, которую мы используем во многих приложениях. Есть много значений по умолчанию, правил проверки, структуры и т. д., которые повторяются. Мы работаем над набором директив, чтобы сделать представление более семантическим и менее подробным.
Есть несколько целей, по которым мы стреляем.
Однократное определение модели контактной формы в родительской директиве следующим образом:
<div my-form model='formModel'>
. Связанные дочерние директивы смогут получить базовую модель из атрибутаmodel
.Укажите конфигурацию по умолчанию (размер, правила проверки, заполнители, классы и т. д.) для каждого входа, но при необходимости разрешите перезапись атрибутов. Таким образом, мы создаем дочерние директивы, используя для связи контроллер директивы
my-form
. Мы также хотим, чтобы эти дочерние директивы были связаны с моделью контроллера приложенияformModel
.
У меня возникли проблемы с реализацией этого.
formModel
отображается через контроллер родительской директивы, но мне приходится вручную$compile
дочернюю директиву использоватьscope.$parent
в функцииlink
. Мне это кажется вонючим, но если я попытаюсь использовать область действия дочерней директивы, скомпилированный HTML-код содержит правильный атрибут (он виден в исходном коде), но он не привязан к контроллеру и не отображается ни в какой области, когда осмотрен с помощью Бэтаранга. Я предполагаю, что добавляю атрибут слишком поздно, но не знаю, как добавить атрибут раньше.Хотя я мог бы просто использовать
ng-model
для каждой дочерней директивы, это именно то, чего я пытаюсь избежать. Я хочу, чтобы результирующее представление было очень чистым, а необходимость указывать имена моделей в каждом поле повторялась и приводила к ошибкам. Как еще я могу это решить?
Вот jsfiddle с работающей, но "вонючей" настройкой того, что я пытаюсь сделать.
angular.module('myApp', []).controller('myCtrl', function ($scope) {
$scope.formModel = {
name: 'foo',
email: '[email protected]'
};
})
.directive('myForm', function () {
return {
replace: true,
transclude: true,
scope: true,
template: '<div ng-form novalidate><div ng-transclude></div></div>',
controller: function ($scope, $element, $attrs) {
$scope.model = $attrs.myModel;
this.getModel = function () {
return $scope.model;
};
}
};
})
.directive('myFormName', function ($compile) {
return {
require: '^myForm',
replace: true,
link: function (scope, element, attrs, parentCtrl) {
var modelName = [parentCtrl.getModel(),attrs.id].join('.'),
template = '<input ng-model="' + modelName + '">';
element.replaceWith($compile(template)(scope.$parent));
}
};
});