Контроллер $scope и ‹form› в TranscludeScope

У меня есть директива, в которой есть трансклюд. Включенный контент представляет собой форму, которая имеет опцию отправки, вызывающую метод в (родительском) контроллере. Этот метод вызывается из включенной области, поэтому к любым переменным, к которым я обращаюсь в контроллере, я могу получить доступ через this.variable, поскольку это отражает область вызывающих (текущую). Однако $scope.variable не определено, поскольку $scope относится к родительской области, которая является областью действия контроллера.

Должен ли я действительно использовать this для доступа к значениям форм или есть соглашение, которое я должен реализовать для доступа через $scope в (родительском) контроллере?

Отказ от ответственности: я знаю, что не использую функциональность контроллера, и прямо сейчас я не могу изменить это для проекта.

Планкер для демонстрации проблемы: http://plnkr.co/edit/TdgZFIRNbUcHNfe3a7uO?p=preview

Как вы можете видеть, значение внутри директивы обновляется при изменении значения в текстовом поле. Это ожидаемо, поскольку оба относятся к включенной области. {{name}} за пределами директивы не изменяется, так как это родительская область, а не включенная область. Одностороннее движение.

Какое правильное решение? Использовать this.name или изменить директиву, чтобы $scope.name можно было использовать вне директивы?

Для тех, кто предпочитает код плункерам:

HTML:

<body ng-app="docsTransclusionExample">
  <div ng-controller="Controller">
    {{name}}
    <my-dialog>
      Check out the contents, {{name}}!
      <form>
        <input ng-model="name">
      </form>
    </my-dialog>
  </div>
</body>

Директива:

(function(angular) {
  'use strict';
angular.module('docsTransclusionExample', [])
  .controller('Controller', function($scope) {
    $scope.name = 'Tobias';
  })
  .directive('myDialog', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      templateUrl: 'my-dialog.html'
    };
  });
})(window.angular);

Шаблон директивы:

<div class="alert" ng-transclude></div>

person bastijn    schedule 14.03.2016    source источник


Ответы (1)


Это связано с «Правилом точки» в angular.

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

Когда вы используете объекты данных, вы получаете доступ к членам «с точкой», поэтому вы не меняете область напрямую и не создаете новую дочернюю область

В твоем случае

$scope.name = 'Tobias';

следует изменить на

$scope.data = {name: 'Tobias'};

см. plunker: http://plnkr.co/edit/RqORVm8r4jph532dT6nY?p=preview

для дальнейшего чтения:

Почему документы AngularJS не используют точку в директиве модели?

https://www.youtube.com/watch?v=DTx23w4z6Kc

PS.

  1. Это не связано с директивным включением (которое касается построения DOM).
  2. Если вы выполните: scope: {} в директиве, вы явно создадите дочернюю область.
person ronapelbaum    schedule 14.03.2016
comment
Спасибо за полный ответ, включая материалы для чтения. Довольно простое исправление. - person bastijn; 15.03.2016