Несколько директив на одной странице с ng-моделью, bindToController

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

Однако я столкнулся со странной проблемой, когда ng-model выходит за пределы изолированной области, а bindToController.

Угловая директива:

    angular.module('quiip.directives')
    .directive('subscribeToNewsletter', subscribeToNewsletterDirective);

    function subscribeToNewsletterDirective(){
        return {
            restrict: 'A',
            scope: {},
            bindToController: true,
            controllerAs: 'subscribe',
            controller: subscribeToNewsletterCtrl,
            link: function(scope, el){
                el.addClass('subscribe-to-newsletter');
            }
        }
    }

HTML-форма, общая структура. Это зависит от того, где используется форма. Это жестко закодировано (т.е. не шаблон):

    <form subscribe-to-newsletter ng-submit="subscribe.submitEmailSubscribe()" ng-class="{ error : subscribe.states.error, success : subscribe.states.success }">
        <div class="status-icon loading" ng-show="subscribe.states.loading"><i class="fa fa-circle-o-notch fa-spin"></i></div>
        <div class="status-icon success" ng-show="subscribe.states.success"><i class="fa fa-check"></i> Subscribed!</div>
        <input type="email" placeholder="Email Address" ng-model="subscribe.email">
        <button type="submit" class="hollow">Subscribe to newsletter</button>
    </form>

Другой пример формы:

    <form class="row" subscribe-to-newsletter ng-submit="subscribe.submitEmailSubscribe()" ng-class="{ error : subscribe.states.error, success : subscribe.states.success }">
        <div class="status-icon loading" ng-show="subscribe.states.loading"><i class="fa fa-circle-o-notch fa-spin"></i></div>
        <div class="status-icon success" ng-show="subscribe.states.success"><i class="fa fa-check"></i> Subscribed!</div>
        <div class="small-12 medium-6 columns">
            <input type="email" ng-model="subscribe.email" placeholder="email" name="email-address">
        </div>
        <div class="small-12 medium-6 columns">
            <button type="submit" class="expand">Subscribe</button>
        </div>
    </form>

Как вы можете видеть на этом снимке экрана, ng-model ускользает как от изолированной области, так и от controllerAs/bindToController (я даже не уверен, что мне нужно использовать оба?) и распространяется по странице.

Что я делаю не так?


person Harley Alexander    schedule 23.10.2015    source источник
comment
Это не имеет ничего общего с вашей директивой. Вы просто используете одну и ту же модель для обоих полей ng-model="subscribe.email".   -  person dfsq    schedule 23.10.2015
comment
Спасибо - у меня сложилось впечатление, что subscribe.email будет использовать объект подписки в изолированной области действия директивы - таким образом, не будет конфликтов на странице. Я использовал ng-model для доступа к значению электронной почты в рамках изолированной директивы!   -  person Harley Alexander    schedule 25.10.2015


Ответы (1)


Вы смешиваете директиву для изоляции области действия с директивой для управления DOM.

Изолировать область

Согласно документам, создание изолированной области позволяет Вам

отделить область внутри директивы от области снаружи, а затем сопоставить внешнюю область с внутренней областью директивы.

Если вы хотите изолировать область вашей формы внутри родительской области и представить модель этой родительской области, вы можете реализовать ее следующим образом:

<!-- parent template -->
<div> <!-- just an example parent template -->

    <subscribe-to-newsletter subscribe-email="subscribe.email"></subscribe-to-newsletter>

</div>

Тогда у вас есть отдельный файл шаблона для вашего кода формы:

<form ng-submit="subscribe.submitEmailSubscribe()".... <!-- note no use of directive name here -->
    ...
</form>

Тогда ваша директива выглядит так

// subscribeToNewsletter.directive.js
angular.module('quiip.directives')
.directive('subscribeToNewsletter', subscribeToNewsletterDirective);

function subscribeToNewsletterDirective() {
    return {
        restrict: 'A',
        scope: {
            subscribeEmail: '=' // bi-directional binding to the model passed into your template handy for attaching data to a parent form object
        },
        bindToController: true,
        controllerAs: 'subscribe',
        controller: subscribeToNewsletterCtrl,
        replace: true,
        templateUrl: 'path/to/your/form/template'
    }
}

Манипуляции с DOM

Чтобы манипулировать DOM, вы можете создать директиву, которая возвращает функцию ссылки (почти то, что вы уже делаете, но без области изоляции).

Хорошим примером этого является в документах. Для вашего стиля кодирования ваша директива может выглядеть так:

angular.module('quiip.directives')
    .directive('subscribeToNewsletter', subscribeToNewsletterDirective);

    function subscribeToNewsletterDirective() {
        return {
            link: link
        }

        function link(scope, element, attrs) {
            element.addClass('subscribe-to-newsletter');
        }
    }

Окончательно...

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

person br3w5    schedule 23.10.2015
comment
Спасибо @ br3w5 за потрясающе подробный ответ ... Проблема с использованием директивы элемента заключается в том, что у меня не может быть другого макета формы для каждого экземпляра. Это была идея с использованием вместо этого атрибута — я мог прикрепить функциональность к любой форме, и это сработало. Думаю, я хочу изолировать поле электронной почты в директиве, чтобы оно не распространялось на родительскую область. Я мог бы использовать el.find('input') val, чтобы обойти ng-модель, но это не похоже на угловой способ... - person Harley Alexander; 25.10.2015
comment
Так является ли цель директивы только в том, чтобы взять адрес электронной почты и отправить его монитору кампании? - person br3w5; 25.10.2015
comment
почему бы не использовать для этого сервис или фабрику? - person br3w5; 03.11.2015