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

Как использовать ng-show в директиве с изолированной областью

У меня есть директива, которую я использую следующим образом:

<dir model="data"></dir>

Директива имеет изолированную область действия.

scope :{
  model:'='
}

Теперь я пытаюсь использовать ng-show в этой директиве, используя другой атрибут моей области $scope, например:

<dir ng-show="show" model="data"></dir>

Но он не работает, потому что директива пытается найти атрибут show в своей области.

Я не хочу, чтобы директива знала о том, что его контейнер может захотеть скрыть его.

Обходной путь, который я нашел, - это обернуть директиву в <div> и применить ng-show к этому элементу, но мне не нравится дополнительный элемент, который заставляет меня использовать:

<div ng-show="show" >
  <dir model="data"></dir>    
</div>

Есть ли лучший способ сделать это?

Смотрите этот плункер: http://plnkr.co/edit/Q3MkWfl5mHssUeh3zXiR?p=preview

4b9b3361

Ответ 1

Вы можете рассмотреть возможность перехода на Angular 1.2 или выше. Область изоляции теперь доступна только для директив с свойством scope. Это означает, что ng-show больше не зависит от вашей директивы, и вы можете написать ее точно так же, как вы пытались сделать это в первую очередь:

<dir ng-show="show" model="data"></dir>

@Angular -Developers: Отличная работа, ребята!

Ответ 2

Обновление:. Этот ответ относится к выпускам Angular до 1.2. См. Ответ @lex82 для Angular 1.2.

Поскольку ваша директива dir создает область выделения, все директивы, определенные в одном и том же элементе (dir в этом случае), будут использовать эту область выделения. Вот почему ng-show ищет свойство show в области изоляции, а не в родительской области.

Если ваша директива dir действительно является автономным/автономным/повторно используемым компонентом , и поэтому она должна использовать область изоляции, ваше упаковочное решение, вероятно, лучше всего (лучше, чем использование $parent, IMO), потому что такие директивы обычно не должны использоваться с другими директивами одного и того же элемента (или вы получаете именно такую ​​проблему).

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

Ответ 3

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

function link($scope, $element, attr, ctrl) {

    if (attr.hasOwnProperty("ngShow")) {
        function ngShow() {
            if ($scope.ngShow === true) {
                $element.show();
            }
            else if($scope.ngShow === false) {
                $element.hide();
            }
        }
        $scope.$watch("ngShow", ngShow);
        setTimeout(ngShow, 0);
    }
    //... more in the link function
}

Вам также понадобится настроить привязки областей для ngShow

scope: {
    ngShow: "="
}

Ответ 4

Просто используйте $parent для родительской области следующим образом:

<dir ng-show="$parent.show" model="data"></dir>

Отказ

Я думаю, что это точный ответ на ваш вопрос, но я признаю, что он не идеален с эстетической точки зрения. Однако обернуть <div> тоже не очень приятно. Я думаю, что это можно оправдать, потому что из другого параметра, переданного в область изоляции, можно видеть, что в директиве фактически есть область выделения. С другой стороны, я должен признать, что я регулярно забываю $parent в первую очередь, а затем задаюсь вопросом, почему он не работает.

Конечно, было бы яснее добавить дополнительный атрибут is-visible="expression" и вставить ng-show внутренне. Но вы заявили в своем вопросе, что пытались избежать этого решения.

Обновление: Не работает в Angular 1.2 или выше.