【问题标题】:Scope function isn't receiving a callback argument范围函数未接收回调参数
【发布时间】:2014-05-11 05:04:41
【问题描述】:

我有一个这样的控制器:

angular.module('main', []).controller('mainCtrl', function ($scope) {
    $scope.doStuff = function (cb) {
        // Do some stuff.
        cb();
    };
});

我有一个这样的指令:

angular.module('action-bar', []).directive('actionBar', function () {
    return {
        restrict: 'EA',
        replace: true,
        template: '<h1>test</h1>',
        scope: {
            doStuff: '&'
        },
        link: function (scope, element, attrs) {
            scope.doStuff(function () {
                alert('callback executed');
            });
        }
    };
});

这里是标记:

<div ng-app="main">
  <div ng-controller="mainCtrl">
    <div ng-action-bar></div>
  </div>
</div>

我可以调用doStuff 就好了,但是cb 参数始终是undefined,即使我传入一个匿名函数作为回调。我在这里做错了什么?

【问题讨论】:

  • 您是否真的将doStuff 属性传递给了HTML 中的actionBar 指令?您没有向我们提供您如何使用它的示例。快速浏览一下,我认为您需要在 HTML 中添加 doStuff="doStuff()" .. 或者创建一个 jsfiddle 以便我们更好地查看它
  • @JoseM 抱歉,我遗漏了标记。该指令包含在由mainCtrl 控制的元素中。因此doStuff函数从控制器作用域继承到隔离作用域中。
  • @Stewie 这不是重复的,因为我不想通过attrs 传递任何东西。我只是想从链接函数中将参数传递给父范围方法。

标签: javascript angularjs scope angularjs-directive angularjs-scope


【解决方案1】:

如果你想使用表达式 ('&') 语法将 doStuff 传递到你的指令中,那么在你的 html 中你应该像这样传递它:

<div action-bar doStuff="doStuff(cb)"></div>

在你的指令的链接函数中你可以这样调用它:

scope.doStuff({cb: function() { ... }});

查看 egghead.io 视频了解更多信息:https://egghead.io/lessons/angularjs-isolate-scope-expression-binding

注意:我个人不喜欢这种语法,所以我总是使用 Jonathan Palumbo 的解决方案(双向绑定)。

【讨论】:

    【解决方案2】:

    将您的隔离范围更改为使用= 而不是&amp; 允许您访问父范围的doStuff 方法。

    angular.module('main', ['action-bar']).controller('mainCtrl', function ($scope) {
        $scope.doStuff = function (cb) {
            // Do some stuff.
            cb();
        };
    });
    
    angular.module('action-bar', []).directive('actionBar', function () {
        return {
            restrict: 'EA',
            replace: true,
            template: '<h1>test</h1>',
            scope: {
                doStuff: '='
            },
            link: function (scope, element, attrs) {
                scope.doStuff(function () {
                    alert('callback executed');
                });
            }
        };
    });
    

    在你的标记中使用指令

    <div ng-app="main" ng-controller="mainCtrl">
        <action-bar do-stuff="doStuff">
        </action-bar>
    </div>
    

    这是一个有效的example。

    【讨论】:

    • 因此,看起来如果您不包含 do-stuff="doStuff" 属性,则它不起作用。有没有办法在不指定标记中的任何属性的情况下实现这一点?
    • 当然,如果您删除隔离范围,例如(scope: { doStuff: '=' },),它应该可以工作,而无需将方法作为参数传递。 Fiddle
    • 我想我不能这样做,因为我的团队有他们拥有隔离范围的理由。我认为我在这里最大的失败是我不知道我刚刚发现的scope.$parent。调用scope.$parent.doStuff(function () { ... }) 似乎按预期工作:)
    • 也可以,虽然在某些情况下使用$parent 会导致头痛。
    • 我可以看到,但在这种情况下,我实际上是在尝试从隔离范围内调用一个简单的父函数。我实际上根本不需要父函数处于隔离范围内。这似乎是“正确”的解决方案,如果有的话。
    【解决方案3】:

    我通过简单地使用scope.$parent 访问父范围来解决这个问题。我实际上并不需要父函数成为指令隔离范围的一部分。

    例子:

    var app = angular.module('app', []);
    
    // Main controller.
    app.controller('mainCtrl', function ($scope) {
      // Initial text added to log.
      $scope.logs = ['App loaded.'];
      // A log function to add additional lines to the log.
      $scope.log = function (text, callback) {
        $scope.logs.push(text);
        if (callback) callback();
      };
    });
    
    // Directive to log lines to the log viewer.
    app.directive('ngLogLine', function () {
      return {
        restrict: 'E',
        template: '<div><input type="text" ng-model="msg" ng-keydown="$event.keyCode === 13 ? log() : null" /><button ng-click="log()">send</button></div>',
        replace: true,
        scope: {},
        link: function (scope, element, attrs) {
          // Create our own log function on our isolate scope.
          scope.log = function () {
            // Call parent log function and pass in a callback.
            scope.$parent.log(scope.msg, function () {
              // Clear the msg, clearing the input.
              scope.msg = '';
            });
          };
        }
      };
    });
    

    Codepen:http://codepen.io/Chevex/pen/eHuaK/

    【讨论】:

      猜你喜欢
      • 2020-09-09
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多