TranscludeScope 中的控制器 $scope 和 <form>

Controller $scope and <form> in TranscludeScope

我有一个包含嵌入的指令。嵌入的内容是一个表单,它有一个提交选项调用(父)控制器中的一个方法。此方法是从嵌入范围调用的,因此我在控制器中访问的任何变量都可以通过 this.variable 访问,因为这反映了调用者(当前)范围。但是,$scope.variable 是未定义的,因为 $scope 是父作用域,即控制器的作用域。

我真的应该使用 this 来访问表单值,还是有一个约定我应该实施以通过(父)控制器中的 $scope 进行访问?

免责声明:我知道我没有使用 controllerAs 功能,现在我无法为项目更改它。

Plunker 演示问题: 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>

这与 angular 中的 "The Dot Rule" 有关。

这意味着,当您具有作用域层次结构时,子作用域试图修改父作用域,它正在创建自己的作用域。

当您使用数据对象时,您访问成员 "with a dot",因此您不会直接更改作用域,也不会创建新的子作用域

你的情况

$scope.name = 'Tobias';

应该改为

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

查看插件: http://plnkr.co/edit/RqORVm8r4jph532dT6nY?p=preview

进一步阅读:

Why don't the AngularJS docs use a dot in the model directive?

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

PS.

  1. 这与指令嵌入无关(这是关于构建 DOM)。
  2. 如果您这样做:scope: {} 在指令中,您明确地创建了一个子作用域。