10

我的指令设置如下:

<div data-directive-a data-value="#33ff33" data-checked="true">
  <div data-directive-b></div>
</div>
  • 我正在使用嵌入来确保directiveB得到渲染。
  • directiveA有一个复选框,用于在选中时更改某些值。
  • 此值需要在directiveAanddirectiveB的范围内可访问。

我已经设法做到这一点,但只能通过引用$$prevSibling- 有没有更好的方法?

这是代码: http: //jsfiddle.net/janeklb/yugQf/(在此示例中,单击复选框只是为了“清除”该值)

--

更深入一点:(directiveA被嵌入其中的内容)的“内容”并不总是directiveB. 其他类似directiveB的指令也将在那里结束。“directiveB类型”将始终在directiveA.

4

2 回答 2

12

为避免将您的组件过多地耦合在一起,我会避免使用$$prevSibling. 最好的解决方案directiveBdirectiveA使用require.

.directive( 'directiveB', function () {
  return {
    require: '^directiveA',
    scope: true,
    link: function ( scope, element, attrs, directiveA ) {
      scope.obj = directiveA.getObj();
    }
  };
})

^require指示该指令的元素上的某处或 DOM 层次结构中它上方的任何元素上的某个位置是一个名为 的指令,directiveA我们想要调用其控制器上的方法。

.directive( 'directiveA', function () {
  return {
    // ...
    controller: function ( $scope ) {
      // ...
      this.getObj = function () {
        return $scope.obj;
      };
    }
  };
})

所以现在在directiveB你可以使用ng-model="obj.attr".

这有很多变化,但考虑到问题的普遍性,我觉得这是最好的方法。这是一个更新的小提琴:http: //jsfiddle.net/yugQf/7/

于 2013-04-04T21:50:34.800 回答
7

@Josh 在他的回答中提到

最好的解决方案directiveBdirectiveA使用require.

我一直在玩这个,我相信控制器directiveA唯一的解决方案(所以+1 Josh)。这是使用 OP 的小提琴的作用域的样子: 范围图片

(反转棕色箭头,您将获得 $$previousSibling 而不是 $$nextSibling。)

除了$$previousSibling,作用域 004 没有隔离作用域 003 的路径。请注意,作用域 004 是directiveA创建的嵌入作用域,由于directiveB不创建新作用域,因此该作用域也被 使用directiveB

由于您希望与之共享的对象directiveB是在directiveA的控制器中创建的,因此我们也不能使用属性在指令之间共享数据。


在指令中创建模型,然后将该模型共享给外部世界是相当不典型的。通常,您需要在指令之外甚至在控制器之外定义模型(听几分钟 Misko)。服务通常是存储模型/数据的好地方。控制器通常应该引用模型中需要投影到与它们关联的视图中的部分。

为简单起见,我将在控制器上定义模型,然后指令将以正常方式访问此模型。出于教学目的,directiveA仍将使用隔离范围,并将使用@Josh 的答案directiveB创建一个新的子范围。scope: new但是任何类型(隔离、新子、无新范围)和组合都可以工作,因为我们已经在父范围中定义了模型。

控制

$scope.model = {value: '#33ff33', checkedState = true};

HTML

<div ng-controller="NoTouchPrevSibling">
   <div data-directive-a data-value="model.value" data-checked="model.checkedState">
      <div data-directive-b></div>
   </div>

出于其他教学原因,我选择将两个模型属性作为单独的属性传递指令 A,但也可以传递整个模型/对象。由于directiveB 将创建一个子范围,它不需要传递任何属性,因为它可以访问所有父/控制器范围属性。

指令

app.directive('directiveA', function () {
    return {
        template: '<div>' 
            + 'inside parent directive: {{checkedState}}'
            + '<input type="checkbox" ng-model="checkedState" />'
            + '<div ng-transclude></div>'
            + '</div>',
        transclude: true,
        replace: true,
        scope: {
              value: '=',
              checkedState: '=checked'
            },
    };
});
app.directive('directiveB', function () {
    return {
        template: '<div>' 
            + '<span>inside transcluded directive: {{model.checkedState}}</span>'
            + '<input type="text" ng-model="model.value" />'
            + '</div>',
        replace: true,
        scope: true
    };
});

范围

范围

请注意,directiveB 的子作用域 (006) 继承自指令 A 的嵌入作用域 (005)。

单击复选框并更改文本框中的值后:

交互后的作用域

请注意,Angular 会处理更新隔离范围属性。正常的JavaScript 原型继承使指令 B 的子范围可以访问model控制器范围 (003) 中的 。

小提琴

于 2013-04-05T04:23:44.970 回答