0

I'm having troubles with the $watchCollection() function. The problem might be the fact that I'm trying to reference a nested part of a JSON document. I really can't figure the problem out.

HTML

<div ng-app="MovieApp">
  <div ng-controller="FilterController as FilterCtrl" ng-init="FilterCtrl.init()">
    <ul ng-repeat="filter in filters">
      <b>{{filter.name}}</b>
      <li ng-repeat="element in filter.elements">
        <input type="checkbox" ng-model="element.ticked" />{{element.name}}
      </li>
    </ul>
  </div>
</div>

JS

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

app.controller('FilterController', function($scope){
  this.init = function(){
    $scope.filters = jsonfilters;
  };

  $scope.$watchCollection('filters', function(newValue,oldValue){
    alert("A filter has been changed");
  });

});

var jsonfilters = [
{
  "name": "Genres",
  "elements": [
    {"name": "Adventure", "ticked": true},
    {"name": "Action", "ticked": true},
    {"name": "Fantasy", "ticked": true},
    {"name": "Science Fiction", "ticked": true},
    {"name": "Family", "ticked": true},
    {"name": "Thriller", "ticked": true},
    {"name": "Animation", "ticked": true},
    {"name": "Comedy", "ticked": true},
    {"name": "Drama", "ticked": true}
  ]
},
{   
  "name": "Companies",
  "elements": [
    {"name": "Warner Bros.", "ticked": true},
    {"name": "Walt Disney Pictures", "ticked": true},
    {"name": "Paramount Pictures", "ticked": true},
    {"name": "Columbia Pictures", "ticked": true},
    {"name": "DreamWorks Animation", "ticked": true},
    {"name": "Universal Pictures", "ticked": true},
    {"name": "Twentieth Century Fox Film Corporation", "ticked": true},
    {"name": "Legendary Pictures", "ticked": true},
    {"name": "Marvel Studios", "ticked": true},
    {"name": "Village Roadshow Pictures", "ticked": true},
    {"name": "Jerry Bruckheimer Films", "ticked": true}
  ]
}
];

What I want to achieve is being able to call a function everytime one of the checkboxes are ticked/unticked. I made a jsfiddle to demo the problem.

1 Answer 1

1

If you don't need $watchCollection, I suggest avoiding it. There is a large cost to using it, aside from the fact that you didn't get it to work.

Instead try using an event to let you know what changed.

I am using the ng-change directive to know when the user clicks on a checkbox.

HTML

<div ng-app="MovieApp">
  <div ng-controller="FilterController as FilterCtrl" ng-init="FilterCtrl.init()">
    <ul ng-repeat="filter in filters">
      <b>{{filter.name}}</b>
      <li ng-repeat="element in filter.elements">
        <input type="checkbox" ng-model="element.ticked" ng-change="filterChanged($event, element)" />{{element.name}}
      </li>
    </ul>
  </div>
</div>

JS

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

app.controller('FilterController', function($scope){
  this.init = function(){
    $scope.filters = jsonfilters;
  };

    $scope.filterChanged = function($event, element) {
    console.log('Filter changed:', element);
  }
});

var jsonfilters = [
  {
    "name": "Genres",
    "elements": [
      {"name": "Adventure", "ticked": true},
      {"name": "Action", "ticked": true},
      {"name": "Fantasy", "ticked": true},
      {"name": "Science Fiction", "ticked": true},
      {"name": "Family", "ticked": true},
      {"name": "Thriller", "ticked": true},
      {"name": "Animation", "ticked": true},
      {"name": "Comedy", "ticked": true},
      {"name": "Drama", "ticked": true}
    ]
  },
  { 
    "name": "Companies",
    "elements": [
      {"name": "Warner Bros.", "ticked": true},
      {"name": "Walt Disney Pictures", "ticked": true},
      {"name": "Paramount Pictures", "ticked": true},
      {"name": "Columbia Pictures", "ticked": true},
      {"name": "DreamWorks Animation", "ticked": true},
      {"name": "Universal Pictures", "ticked": true},
      {"name": "Twentieth Century Fox Film Corporation", "ticked": true},
      {"name": "Legendary Pictures", "ticked": true},
      {"name": "Marvel Studios", "ticked": true},
      {"name": "Village Roadshow Pictures", "ticked": true},
      {"name": "Jerry Bruckheimer Films", "ticked": true}
    ]
  }
];

See my jsfiddle here: https://jsfiddle.net/intervalia/5k7ehswt/2/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.