使用嵌入隐藏内部元素的父范围的指令范围

Directive scope using transclusion hiding parent scope of inner elements

本文关键字:范围 指令 元素 内部 隐藏      更新时间:2023-09-26

我正在尝试实现一个指令,该指令将使用ng-show$timeout延迟容器的出现。

这是我的指令的样子:

angular.module('myApp')
    .directive('delay', function($timeout) {
        return {
            template: '<div ng-show="showIt" ng-transclude></div>',
            replace: false,
            transclude: true,
            scope:true,
            restrict: 'A',
            link: function postLink(scope, element, attrs) {
                $timeout(function() {
                        scope.showIt = true;
                }, attrs.delay);
            }
        };
    });

然后,我会像这样在我的视图中使用它

<div delay="1000">
    <intput type="text" ng-model="myText"/>
</div>

到目前为止,延迟有效。是的,我很自豪。但是,无法再从控制器访问myText,因为它对父作用域不可见。我尝试将范围更改为以下内容:

scope: {
    myText: '='
}

建立双向数据绑定...没有任何成功。

使用指令实现我尝试实现的目标的最简单方法是什么?多谢!

编辑:黄金法则

非常感谢格雷格尔的回答!

最好的方法是简单地将我的ng模型包装在一个对象中,以使用点符号来避免将ng模型绑定到子范围。子作用域使用原型继承来查找其值,因此在子作用域中设置该值后,它将不再查找父作用域。

解决这个问题的最好方法是记住我所说的"AngularJS黄金法则":

始终在 ng 模型表达式中使用点/句点 (.(。

这样,您将属性写入正确作用域上的正确对象。

但是,如果你真的想让它工作,你可以做一个指令,利用 link 函数的 transclude 参数对正确的范围进行手动嵌入。

sample.directive('delay', function($timeout) {
  return {
    template: '<div ng-show="showIt"></div>',
    replace: false,
    transclude: true,
    scope: {},
    restrict: 'A',
    link: function postLink(scope, element, attrs, nullCtrl, transclude) {
      var transcludeScope = scope.$parent;
      transclude(transcludeScope, function(clone) {
        element.find('div[ng-show]').append(clone);
      });
      $timeout(function() {
        scope.showIt = true;
      }, attrs.delay);
    }
  };
});

这会将<div ng-show="showIt">的内容范围设置为 delay 指令所在的元素的范围。它还具有具有隔离范围的优点,因此您可以在任何位置使用多个实例。

在 Plunkr 中查看它的实际效果

尝试{scope: false} .您正在使用 delay 指令创建自己的作用域。

link: function(scope, element) {
  var showing = true;
  $timeout(function() {
    if (showing) {
      element.hide();
    } else {
      element.show();
    }
    showing = !showing;
  }, delay)
}