【问题标题】:AngularJS - binding/linking two directives togetherAngularJS - 将两个指令绑定/链接在一起
【发布时间】:2015-09-08 10:31:38
【问题描述】:

将两个指令链接/绑定在一起的首选方法是什么?我有一个带有两个指令的控制器,第一个指令是一个选择元素,选择选项后,第二个指令应该处理选定的项目值。

应用代码:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function() {
  var sharedData = { selectedId: '' };

  var vm = this;

  vm.sharedData = sharedData;
});

app.directive('directiveA', ['$compile', function($compile) {
  return {
    restrict: 'E',
    scope: {
      selectedId: '='
    },
    template: '<select data-ng-model="vm.sharedData.selectedId" data-ng-options="currentSelect.Id as currentSelect.Name for currentSelect in vm.sharedData.availableSelects track by currentSelect.Id"><option value="">Select option</option></select><p>Directive A, selected ID: {{vm.sharedData.selectedId}}</p>',
    bindToController: true,
    controllerAs: 'vm',
    controller: function() {
      vm = this;

      vm.sharedData = {
        availableSelects: [
          {Id:1, Name: 'Option 1'},
          {Id:2, Name: 'Option 2'},
          {Id:3, Name: 'Option 3'},
          {Id:4, Name: 'Option 4'}
        ]
      }
      vm.logMessage = logMessage;

      function logMessage(selectedId) {
        console.log('directiveA: ' + selectedId);
      }
    },
    link: function($scope, elem, attr, ctrl) {
      attr.$observe('selectedId', function(selectedId) {
        ctrl.logMessage(selectedId);
      });
    }
  };
}]);

app.directive('directiveB', ['$compile', function($compile) {
  return {
    restrict: 'E',
    scope: {
      selectedId: '='
    },
    template: '<p>Directive B, selected ID: {{vm.sharedData.selectedId}}</p>',
    bindToController: true,
    controllerAs: 'vm',
    controller: function() {
      vm = this;

      vm.logMessage = logMessage;

      function logMessage(selectedId) {
        console.log('directiveB: ' + selectedId);
      }
    },
    link: function($scope, elem, attr, ctrl) {
      attr.$observe('selectedId', function(selectedId) {
        ctrl.logMessage(selectedId);
      });
    }
  };
}]);

HTML 代码:

<!DOCTYPE html>
<html data-ng-app="plunker" data-ng-strict-di>
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link href="style.css" rel="stylesheet" />
    <script data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js" data-require="angular.js@1.4.x"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl as vm">
    <p>MainCtrl, selected ID: {{vm.sharedData.selectedId}}</p>
    <directive-a data-selected-id="vm.sharedData.selectedId"></directive-a>
    <directive-b data-selected-id="vm.sharedData.selectedId"></directive-b>
  </body>

</html>

这是一个 Plunker 示例:

http://plnkr.co/edit/KVMGb8uAjUwD9eOsv72z?p=preview

我做错了什么?

最好的问候,

【问题讨论】:

标签: javascript angularjs angularjs-directive


【解决方案1】:

关键问题围绕着您对孤立作用域的使用:

scope: {
  selectedId: '='
},

使用控制器作为绑定:

controllerAs: 'vm',

这本质上是做什么的,简单地说,就是将视图模型放在指令范围内,通过您在控制器中分配的别名进行访问。所以基本上在你去的时候在你的html中:

<directive-a data-selected-id="vm.sharedData.selectedId"></directive-a>

您实际上是在访问指令-视图模型,而不是 MainCtrl 视图模型。因为您将指令-a 设置为具有隔离范围...这是一个新范围,与 MainCtrl 隔离。

您需要做的更多的是以下几行:

http://plnkr.co/edit/wU709MPdqn5m2fF8gX23?p=preview


编辑

TLDR:我建议在使用隔离范围时使用唯一的视图模型别名 (controllerAs),以正确反映它们不是同一个视图模型的事实。

【讨论】:

  • 补充一点:基本上我所做的是让 MainCtrl vm 存储 selectedId,然后通过 MainCtrl 视图模型 (mainVm) 将其双向绑定到两个子指令。这个属性然后绑定到子指令对应的视图模型:aVm 和 bVm。当他们更改或访问这些属性时,由于隔离范围声明中的双向绑定,他们实际上将访问父 mainVm.selectedId 属性。
  • 谢谢,这正是我需要的!我忘记了“controllerAs”模型的不同名称。
  • 很高兴我能帮上忙 :) 理解作用域始终是 Angular 的重要组成部分,而 controllerAs(连同 bindToController)在帮助消除绑定对象/变量的歧义方面大有帮助。所以很高兴看到您尝试使用这种模式。
  • 如果该帖子有帮助,也将不胜感激将帖子标记为答案;)一切顺利!
猜你喜欢
  • 2016-03-25
  • 1970-01-01
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多