2014-12-01 3 views
1

У меня есть следующий код:Изолированная сфера не обновляется

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

 
testApp.directive('myDirective', function() { 
 
    return { 
 
     scope: { 
 
      child: '=child' 
 
     }, 
 
     
 
     controller: function ($scope, $element, $attrs) { 
 
      $scope.$on('childChanged', function (event, newChild) { 
 
       if ($scope.child.id != newChild.id) { 
 
        alert("The child in the isolated scope is not updated!"); 
 
       } 
 
       else { 
 
        alert("success");      
 
       } 
 
      }); 
 
     } 
 
    }; 
 
}); 
 

 
testApp.controller('myController', function ($scope) { 
 
    $scope.parentObject = {childObject: {id:1}}; 
 
    $scope.changeChild = function changeChild() 
 
    { 
 
     var newChild = { id: $scope.parentObject.childObject.id + 1}; 
 
     $scope.parentObject.childObject = newChild; 
 
     //$scope.$apply(); //This solves the problem 
 
     $scope.$broadcast('childChanged', newChild); 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div data-ng-app="testApp"> 
 
    <div data-ng-controller="myController">   
 
     <div my-directive child="parentObject.childObject"></div> 
 
     <button data-ng-click="changeChild()">Change Child</button> 
 
    </div> 
 
</div>

Объяснение:

  • Я создаю изолированную область для директивы, с двухсторонним привязка к объекту (parentObject.childObject) родительской области.
  • При нажатии на кнопку функция changeChild вызывается в myController. Эта функция заменит $ scope.parentObject.childObject другим ребенком и будет транслировать событие.
  • Слушатель этого события находится в контроллере директивы. В прослушивателе мы проверяем, является ли дочерний объект в изолированной области ($ scope.child) тем же самым, что и тот, который был отправлен в событии (то есть, объект scope.parentObject.childObject родителя). Мы видим, что они не совпадают, то есть ребенок, которого мы получили в , выделенная область еще не обновлена.

Обратите внимание, что если я использую $ scope. $ Apply() перед трансляцией, тогда будет обновляться $ scope.child в контроллере директивы, однако это вызовет следующее исключение: «$ apply уже применяется прогресс".

Может кто-то, пожалуйста, помогите мне понять, что здесь происходит? Почему приложение $ scope. $ Применило помощь, даже если оно только выкидывало экскремент? Как это можно решить, не обращаясь к $ scope. $ Apply? Я хотел бы знать, есть ли способ гарантировать, что связанное свойство в изолированной области будет обновляться после его изменения в области родителя без необходимости передавать его в событии.

Спасибо

ответ

0

Вы можете использовать $ таймаут для вызова следующего переваривать цикла после обновления child.id

Пожалуйста, смотрите демо ниже

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

 
testApp.directive('myDirective', function() { 
 
    return { 
 
    scope: { 
 
     child: '=child' 
 
    }, 
 

 
    controller: function($scope, $element, $attrs) { 
 
     $scope.$on('childChanged', function(event, newChild) { 
 

 
     if ($scope.child.id != newChild.id) { 
 
      alert("The child in the isolated scope is not updated?"); 
 
     } else { 
 
      alert("success"); 
 
     } 
 
     }); 
 

 
    } 
 
    }; 
 
}); 
 

 
testApp.controller('myController', function($scope, $timeout) { 
 
    $scope.parentObject = { 
 
    childObject: { 
 
     id: 1 
 
    } 
 
    }; 
 
    $scope.changeChild = function changeChild() { 
 
    var newChild = { 
 
     id: $scope.parentObject.childObject.id + 1 
 
    }; 
 
    $scope.parentObject.childObject = newChild; 
 

 
    $timeout(function() { 
 
     $scope.$broadcast('childChanged', newChild); 
 
    }, 0); 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div data-ng-app="testApp"> 
 
    <div data-ng-controller="myController"> 
 
    <div my-directive child="parentObject.childObject"></div> 
 
    <button data-ng-click="changeChild()">Change Child {{parentObject.childObject}}</button> 
 
    </div> 
 
</div>

+0

Спасибо, это действительно решает проблему. Я новичок в js и AngularJs, не могли бы вы объяснить, почему это решение работает? Является ли это лучшей практикой для таких случаев? (Извините, я не могу проголосовать, я тоже новичок в stackoverflow ...) – user2051749

+0

@ user2051749 В вашем примере, когда вы транслировали newChild angularjs, во время цикла дайджеста и newChild не обновлялся, вам нужно вызвать еще один цикл дайджеста, чтобы новое значение brodcast (http://stackoverflow.com/questions/16066239/defer-angularjs-watch-execution-after-digest-raising-dom-event). Я скорее использую $ watch в директиве вместо $ broadcast, см. Здесь http://jsbin.com/nibopa/1/edit – sylwester

+0

Спасибо за объяснение. Я попробовал использовать $ watch перед отправкой вопроса, но получил «undefined» как в newValue, так и в oldValue. Не знаю, почему, так как ваш пример (jsbin.com/nibopa/1/edit) работает отлично, и код кажется таким же, как мой ... :( После того, как я увидел следующее сообщение, я попытался использовать вместо этого $ broadcast: http://www.benlesh.com/2013/10/title.html – user2051749

Смежные вопросы