AngularJS:父范围未在指令(具有隔离范围)双向绑定中更新

时间:2014-03-21 11:31:53

标签: angularjs

我有一个带有隔离范围的指令,其值为双向绑定到父范围。我正在调用一个方法来更改父作用域中的值,但是我的指令中没有应用更改。(不会触发双向绑定)。这个问题非常相似:

AngularJS: Parent scope not updated in directive (with isolated scope) two way binding

但我没有更改指令中的值,只是在父作用域中更改它。我读了解决方案,在第五点说:

The watch() created by the isolated scope checks whether it's value for the bi-directional binding is in sync with the parent's value. If it isn't  the parent's value is copied to the isolated scope.

这意味着当我的父值更改为2时,会触发监视。它检查父值和指令值是否相同 - 如果不相同,则复制到指令值。好的,但我的指示值仍然是1 ...我缺少什么?

html:

<div data-ng-app="testApp">
    <div data-ng-controller="testCtrl">
        <strong>{{myValue}}</strong>
        <span data-test-directive data-parent-item="myValue" 
            data-parent-update="update()"></span>
    </div>
</div>

js:

var testApp = angular.module('testApp', []);

testApp.directive('testDirective', function ($timeout) {
    return {
        scope: {
            key: '=parentItem',
            parentUpdate: '&'
        },
        replace: true,
        template:
            '<button data-ng-click="lock()">Lock</button>' +
            '</div>',
        controller: function ($scope, $element, $attrs) {
            $scope.lock = function () {
                console.log('directive :', $scope.key);

                 $scope.parentUpdate();
                 //$timeout($scope.parentUpdate); // would work.

                 // expecting the value to be 2, but it is 1
                 console.log('directive :', $scope.key);
            };
        }
    };
});

testApp.controller('testCtrl', function ($scope) {
    $scope.myValue = '1';
    $scope.update = function () {
        // Expecting local variable k, or $scope.pkey to have been
        // updated by calls in the directive's scope.
        console.log('CTRL:', $scope.myValue);
        $scope.myValue = "2";
        console.log('CTRL:', $scope.myValue);
    };
});

Fiddle

5 个答案:

答案 0 :(得分:22)

更改控制器中的$scope.$apply()后使用$scope.myValue,如:

testApp.controller('testCtrl', function ($scope) {
    $scope.myValue = '1';
    $scope.update = function () {
        // Expecting local variable k, or $scope.pkey to have been
        // updated by calls in the directive's scope.
        console.log('CTRL:', $scope.myValue);
        $scope.myValue = "2";
        $scope.$apply();
        console.log('CTRL:', $scope.myValue);
    };
});

答案 1 :(得分:14)

答案使用$ scope。$ apply()完全不正确。

我看到更新指令范围的唯一方法是:

angular.module('app')
.directive('navbar', function () {
    return {
        templateUrl: '../../views/navbar.html',
        replace: 'true',
        restrict: 'E',
        scope: {
            email: '='
        },
        link: function (scope, elem, attrs) {
            scope.$on('userLoggedIn', function (event, args) {
                scope.email = args.email;
            });
            scope.$on('userLoggedOut', function (event) {
                scope.email = false;
                console.log(newValue);

            });

        }
    }
});

并在控制器中发出您的事件,如下所示:

$rootScope.$broadcast('userLoggedIn', user);

这感觉就像这样一个黑客,我希望角度大师可以看到这篇文章,并提供一个更好的答案,但因为这是接受的答案甚至没有工作,只是给出错误$摘要已经在进行中

答案 2 :(得分:8)

使用$ apply()就像接受的答案一样,也会导致各种错误和潜在的性能提升。设置广播和诸如此类的很多工作。我发现简单的解决方法只是使用标准超时来触发下一个周期中的事件(由于超时将立即触发)。围绕parentUpdate()调用,如下所示:

$timeout(function() {
    $scope.parentUpdate();
});

完美适合我。 (注意:0ms是未指定时的默认超时时间)

答案 3 :(得分:4)

大多数人忘记的一件事是,您不能仅使用对象表示法声明隔离范围,并期望绑定父范围属性。这些绑定仅在声明了绑定“魔法”工作的属性时才有效。有关更多信息,请参阅:

https://umur.io/angularjs-directives-using-isolated-scope-with-attributes/

答案 4 :(得分:0)

请尝试使用$scope.$apply()

,而不是使用$scope.$applyAsync();