javascriptangularjscheckboxangularjs-ng-repeatangularjs-controlleras

Errors when using 'ControllerAs' but works fine when using '$scope' in ng-repeat checkbox


When using '$scope' syntax, checking on individual checkbox correctly outputs its corresponding object name but when applying 'ControllerAs' syntax to same code, checking on individual checkbox abnormally generates error

$scope.users = [{.....}] //using $scope syntax
$scope.selected = [];

$scope.exist = function(item) {
  return $scope.selected.indexOf(item) > -1;
}
$scope.toggleSelection = function(item) {
  var idx = $scope.selected.indexOf(item);
  if (idx > -1) {
    $scope.selected.splice(idx, 1);
  } else {
    $scope.selected.push(item);
  }
}

Representation of above code using in ControllerAs

vm.users = [{....}] //Using 'Controller As' Syntax
vm.selected = [];

vm.exist = function(item) {
  return vm.selected.indexOf(item) > -1;
}
vm.toggleSelection = function(item) {
  var idx = vm.selected.indexOf(item);
  if (idx > -1) {
    vm.selected.splice(idx, 1);
  } else {
    vm.selected.push(item);
  }
}

Error returned in chrome developer tools

TypeError: vm.selected.indexOf is not a function at GridController.vm.exist (gridController.js:37)

Demo Controller As, http://plnkr.co/edit/5auLDGbpyDFUcpPxBzNs?p=preview

Demo $Scope, http://plnkr.co/edit/2jz0ieeCWJE6tvzXK69A?p=preview

Please what could be the issue or could this be a bug when Controller As syntax is applied in this context, thanks


Solution

  • your toggleSelection function is doing a similar job to ng-model, except that ng-model has a selected property for each user in your $scope code, but a singular vm.selected property in the Controller As version, due to how JavaScript Prototype Inheritance works with primitives. This is a prime example of where not using a . in bindings causes an unexpected result.

    The ng-model in this case is changing vm.selected from an array into a boolean, which is cascading to an error in your exist function, which now sees a boolean that doesn't have a .indexOf property.

    In this case, your toggleSelection code is doing what you need for the rest of your code logic, and you don't actually need ng-model.