0

В приведенном выше примере, когда я изменяю массив значений, переданный директиве от контроллера, все изменения отражаются в директиве html. Я имею в виду, что вижу изменения в пользовательском интерфейсе.Угловое связывание не работает в пользовательской директиве для локальных переменных области, вычисленных с использованием переданных данных

Но изменения в значении переменной $scope.message не получает отражение, даже если значение $scope.message вычисляется из значения $scope.myData, значение которого становится изменено с помощью $timeout в родительском контроллере Чтобы увидеть эти изменения в $scope.message, вам необходимо посмотреть массив, используя $watchCollection. Мои вопросы,

  1. Почему угловое связывание не работает для $scope.myData нормально?
  2. Что такое другие «известные» угловые случаи, когда привязка углов не работает?

Ниже приведен фрагмент кода

(function(){ 
    angular.module("csjoshi04.2waybinding",[]) 
      .controller("ParentCtrl",["$scope", "$timeout", function($scope, $timeout){ 
       $scope.myCars = ["Ford", "BMW", "Toyata"]; 
       $timeout(function(){ 
        $scope.myCars.push("Honda"); 
       }, 3000); 
      }]) 
      .directive("showMyData",function(){ 
       return { 
        restrict: "E", 
        scope: { 
         myData : "=" 
        }, 
        controller : ["$scope", function($scope){ 
         $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
        }], 
        template : '<div>{{message}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
       } 
      }) 
})() 

Ниже HTML

<body ng-controller="ParentCtrl"><show-my-data my-data="myCars" ></show-my-data></body> 

Для того, чтобы выше директивы работы, я сделал ниже изменения

directive("showMyData",function(){ 
       return { 
        restrict: "E", 
        scope: { 
         myData : "=" 
        }, 
        controller : ["$scope", function($scope){ 
         $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
         $scope.$watchCollection(function(){ 
          return $scope.myData; 
         }, function(new1, old){ 
          $scope.message = ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
         }); 
        }], 
        template : '<div>{{message}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
       } 
      }) 

здесь ссылка plunkr.

plunker

ответ

0

Я бы не назвал это «угловой случай» связывания данных в угловой.

Функция привязки данных Angular позволяет непрерывно проверять значения, привязанные к $ scope. Это круто, но это не волшебство, на императивном языке, таком как JavaScript-заявление. $scope.message = condition ? "message": "another message"; сам по себе не предполагает, что выражение будет повторно оцениваться снова. Угловой инициализирует контроллер только один раз для привязки к шаблону, и это точно, сколько раз будет выведено выражение в приведенном выше примере. Один раз. После этого это просто другая переменная $scope, значение которой является либо «сообщением», либо «другим сообщением», и именно так оно и будет, если мы не изменим его сами.

Вы сами определили проблему. Значение $scope.message зависит от $scope.myData, но без $watchCollection не должно быть хорошей привязки. $watchCollection, с другой стороны, будет продолжать переоценивать сначала $scope.myData;, а затем функции $scope.message = ..., потому что это то, что делает угловой.

Лично я бы сделал это с функцией getter вместо присвоения значения $scope и вручную обновил его. Это ближе к тому, что вы изначально пытались сделать в любом случае.

.directive("showMyData",function(){ 
    return { 
     restrict: "E", 
     scope: { 
      myData : "=" 
     }, 
     controller : ["$scope", function($scope){ 
      $scope.getMessage = function(){ 
       return ($scope.myData.indexOf("Honda") > -1 && $scope.myData.length >= 4) ? "1 out of 4 cars is always Honda": "OOPS, no honda cars"; 
      };  
     }], 
     template : '<div>{{getMessage()}}</div><ul ng-repeat="data in myData"><li>{{data}}</li></ul>' 
    } 
}) 

Теперь, когда мы используем вызов функции вместо простого значения, то выражение, которое создает сообщение получает переоценено снова и снова, обновляя вид, когда это необходимо.

+0

Это действительно хорошее решение.Это также помогает не использовать $ scope. $ Watch/Collection. Один вопрос, однако, в этой проблеме почему функция геттера всегда получает оценку, а сообщение - нет? – csjoshi04

+0

Оба они оцениваются. С '$ scope.message' код контроллера запускается один раз, а' $ scope.message' будет «OOPS, без автомобилей Honda», потому что когда он запускается, нет хонд. Угловой будет проверять, что такое значение '$ scope.message', но оно не изменится. Угловое не может получить доступ или повторно использовать ваш код '$ scope.message = ($ scope.myData.indexOf (" Honda ") ...'. Эта проверка индекса будет выполняться один раз, а затем ее не будет, присваивается 'message', а не весь оператор. – noppa

+0

Именно так заявления работают на многих языках программирования, но функции разные. Код внутри них может и будет подвергаться повторной оценке столько раз, сколько мы хотим. В отличие от простого сообщения значение, угловое может вызвать функцию снова и снова, прося ее переоценить значение. – noppa