【问题标题】:Share Directive Scope with Transcluded Elements与嵌入元素共享指令范围
【发布时间】:2014-04-07 16:48:28
【问题描述】:

我正在编写一个可重用的模态指令,但嵌入的元素会创建自己的范围。这是该问题的JSFIDDLE。这是它的工作原理。

<button ng-click="show=!show">Show Modal</button>
<modal visible="show">
    <button ng-click="show=!show">X</button>
</modal>

请注意,显示它的按钮有效,但 X 并没有关闭它,因为内部按钮被嵌入并创建了自己的范围。有没有办法将嵌入的范围链接到指令的当前范围?或者只是阻止它创建自己的范围?这是指令。

.directive('modal', function($compile) {
return {
  restrict: 'E',
  template: "<div ng-style='bgstyling()' ng-transclude></div>",
  transclude: true,
  link: function(scope, elem, attrs) {
    scope.$watch(attrs.visible, function(val) {
      elem[0].style.visibility = val ? 'visible' : 'hidden';   
    });
    scope.bgstyling = function() {
      return {
        'position': 'fixed',
        'top': '0',
        'left': '0',
        'bottom': '0',
        'right': '0',
        'backgroundColor': attrs.bgColor || '#000',
        'opacity': attrs.opacity || '0.85'
      }
    }
  }
}

})

* 更新 *

我认为答案可能与链接函数的transclude函数参数有关。这是我刚刚尝试过的,但仍然无法正常工作。

link: function(scope, elem, attrs, nullC, transclude) {
    transclude(scope, function(clone) {
      elem.append($compile(clone)(scope));
    });
    ...

【问题讨论】:

  • 我认为X 正在从孤立的指令范围中获取范围。但是在 html 中设置 show 没有影响,因为指令范围属性名称是 ngModalShow
  • @Chandermani,是的,这只是我提出的快速示例。现在看看。我希望在 scope.show 更改时更改可见性。我认为关键可能是链接的 transcludeFn,但我看不到它是如何工作的。

标签: angularjs


【解决方案1】:

让控制器负责更新范围会有所帮助 - 毕竟范围是共享的,您可能希望在同一个地方更新它的逻辑。

.controller("testCtrl", function($scope) {
  $scope.show = false;
  $scope.toggle = function() {
    $scope.show = !$scope.show;
  };
})

还有模板:

<div ng-app="test" ng-controller="testCtrl">
  <button ng-click="toggle()">Show Modal</button>
  <modal visible="show">
    <button ng-click="toggle()">X</button>
  </modal>
</div>

看看这个JSFiddle

【讨论】:

  • 更具体地说,您还可以在指令本身中引用控制器。
  • 这很好用。为什么使用toggle() 有效,但show=!show 失败?他们确实做同样的事情。
【解决方案2】:

关闭按钮是特定于 Modal 指令的,因此您只需将按钮放在指令 html 中即可避免范围问题。

jsfiddle

...      
template: "<div ng-style='bgstyling()'><button ng-click=\"show=!show\">X</button></div>",
...

如有必要,您还可以访问父作用域,但我更喜欢尝试使作用域尽可能简单。

编辑 你仍然可以像 jsfiddle 中那样使用 transclude

...
template: "
    <div ng-style='bgstyling()'>
        <button ng-click=\"show=!show\">X</button>
        <div ng-transclude></div>
    </div>
    ",
transclude: true,
...

【讨论】:

  • 这违背了我想要做的事情的目的。我想创建一个显示任何内部内容的模式。您描述的方式不可重复使用。谢谢你。
  • 您仍然可以像以前一样使用 transclude。内容将出现在内部 div 中,而不是在上面的编辑中显示的外部 div。
  • 谢谢,但我的想法是我不希望指令中的按钮,它需要能够在被嵌入时关闭它。
  • 好吧,这听起来很公平。如果我能提供帮助,我宁愿不使用 transclude,并且通常通过范围传递数据以便更明确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多