【问题标题】:AngularJS Directive Isolate Scope Not Updating ParentAngularJS指令隔离范围不更新父
【发布时间】:2014-03-16 18:06:57
【问题描述】:

我有一个指令,它有一个模型绑定 2 方式,当通过 ng-click 调用 save() 方法时,父范围不会更新,除非我调用 $scope.$apply() 然后抛出$apply 已经在进行中的错误。

我正在使用 ngResource,事件有一个监听器调用 $scope.model.$save();

有解决办法吗?还是我做错了什么?

.directive('editable', function(){
    return {
        restrict: 'AE',
        templateUrl: '/assets/partials/editable.html',
        scope: {
            value: '=editable',
            field: '@fieldType'
        },
        controller: function($scope){

           ...

            $scope.save = function(){
                $scope.value = $scope.editor.value;
                $scope.$emit('saved');
                $scope.toggleEditor();
            };

        }
    };
})

更新

看起来它毕竟是在更新父级,但在摘要完成之前发射就被触发了。我可以使用 $timeout 将其强制到堆栈的末尾,但感觉有点笨拙。有没有更好的办法?

$scope.$on('saved', function(){
    $timeout(function(){
        $scope.contact.$update();
    }, 0);
});

【问题讨论】:

  • 你能在 jsfiddle 或 plunkr 中显示这个吗?
  • 它看起来在这里工作,但这只是隔离范围更新中的值。 jsfiddle.net/Rw46r/1 如果我查看 Batarang,我可以看到父级没有被更新。
  • 我不确定这将如何帮助强制更新父范围?正如我所说,当我强制使用 $scope.$apply(); 时,它似乎有效。但这并不理想。
  • 如果你通过一个对象然后更新它应该工作的对象的属性。问题是字符串在 javascript 中是不可变的,所以它实际上只是替换本地引用而不是更新值。这是一个更新的小提琴,看看这是否符合您的预期jsfiddle.net/Rw46r/4
  • 不幸的是,这不适用于指令试图实现的目标。有点玩,似乎父级实际上正在更新,只是比发出的偶数要慢。

标签: javascript angularjs scope


【解决方案1】:

你如何调用 $scope.save ?如果您使用其中一个 angular 指令,例如 ng-click,angular 会自动为您运行一个摘要循环,因此您不需要调用 $scope.$apply()。在内部,Angular 在开始另一个循环之前检查摘要是否已经在进行中,因此如果您使用其中一个内置指令,它将为您处理已经在进行中的摘要问题。例如,将其放入指令的模板中...

<button ng-click="save()">Save</button>

如果您需要从控制器或链接函数调用保存,您可以做一些小技巧来防止“正在消化”错误。使用 $timeout 服务将调用推迟到调用堆栈的末尾...

$scope.save();
$timeout(function() {
    $scope.$apply();
}, 0);

我们将超时设置为 0,因此没有真正的延迟,但这仍然足以将 $apply 调用推送到当前调用堆栈的末尾,这允许正在进行的摘要首先完成并且防止错误。这并不理想,可能意味着您的设计存在更大的问题,但有时您只需要让它工作

【讨论】:

  • 是的,我们正在使用 ng-click,这就是为什么我认为 $scope.$apply() 是必要的很奇怪 - 事实证明并非如此。问题似乎是在摘要完成更新之前发出了我们的事件,因此我们将旧数据发送到服务器。我已经在 $scope.$on() 处理程序中使用了 $timeout() ,但感觉真的很hacky。 $scope.$watch() 可能是更好的解决方案?
  • 这是我现在正在做的,感觉有点脏gist.github.com/steve228uk/f1f5923d4ed89f4356d1
  • 是的,我刚刚阅读了 cmets。在回答之前可能应该这样做:) 我更喜欢 $scope.$watch 事件。如果我正确理解您的设计,它对这类事情很有用。如果没有,另一种选择是只在事件中传递新值,例如.. $scope.$emit('saved', $scope.value);并抓住它像.. $scope.$on('saved', event, newValue)
  • 这听起来可能是一个更优雅的解决方案。要把活动换成手表。 更新: watch 实际上在这里不起作用,所以我想我可以通过这个值来代替。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多