Подтвердить что ты не робот

AngularJS: размер родителя не обновляется в директиве (с изолированной областью), двусторонней привязкой

У меня есть директива с изолированной областью со значением с двухсторонней привязкой к родительской области. Я вызываю метод, который изменяет значение в родительской области, но это изменение не применяется в моей директиве. (Двухсторонняя привязка не запускается). Этот вопрос очень похож:

AngularJS: область родительского контроля не обновляется в директиве (с изолированной областью) двусторонняя привязка

но я не изменяю значение из директивы, но меняю ее только в родительской области. Я прочитал решение, и в пункте 5 сказано:

The watch() created by the isolated scope checks whether it value for the bi-directional binding is in sync with the parent value. If it isn't  the parent 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 scope.
        console.log('CTRL:', $scope.myValue);
        $scope.myValue = "2";
        console.log('CTRL:', $scope.myValue);
    };
});

Fiddle: http://jsfiddle.net/u69PT/17/

4b9b3361

Ответ 1

Используйте $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 scope.
        console.log('CTRL:', $scope.myValue);
        $scope.myValue = "2";
        $scope.$apply();
        console.log('CTRL:', $scope.myValue);
    };
});

Ответ 2

Ответ Используйте $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);

Это похоже на такой взлом. Я надеюсь, что гуру angular могут увидеть это сообщение и дать лучший ответ, но так как принятый ответ даже не работает и просто дает ошибку $digest уже в процессе

Ответ 3

Использование $apply(), как и принятый ответ, может вызвать всевозможные ошибки и потенциальные удары производительности. Настройки для трансляции и многое другое для этого. Я нашел простое обходное решение просто использовать стандартный тайм-аут для запуска события в следующем цикле (который будет немедленно из-за таймаута). Окружите вызов parentUpdate() следующим образом:

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

Прекрасно подходит для меня. (примечание: 0мс - это время ожидания по умолчанию, если не указано)

Ответ 4

Одна вещь, которую большинство людей забывает, состоит в том, что вы не можете просто объявить изолированную область видимости объекта и ожидать, что свойства родительской области будут связаны. Эти привязки работают только в том случае, если объявлены атрибуты, через которые работает привязка "магия". См. Дополнительную информацию:

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

Ответ 5

Вместо использования $scope.$apply() попробуйте использовать $scope.$applyAsync();