指令范围使用包含隐藏内部元素的父范围的转义

时间:2014-12-02 01:51:44

标签: javascript angularjs angularjs-directive angularjs-scope

我正在尝试使用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: '='
}

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

使用指令实现我想要实现的最简单的方法是什么?非常感谢!

编辑:黄金法则

非常感谢GregL的回答!

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

2 个答案:

答案 0 :(得分:3)

解决这个问题的最佳方法是牢记我所谓的“AngularJS黄金法则”:

  

始终在ng-model表达式中使用点/句点(。)。

这样,您将把属性写入正确范围内的正确对象。

但是,如果你真的想让它工作,你可以做一个指令,利用链接函数的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指令所在元素的范围。它还具有隔离范围的优点,因此您可以在任何地方使用多个实例。

See it in action in a Plunkr

答案 1 :(得分:0)

试试{scope: false}。您正在使用delay指令创建自己的范围。

或者

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