0

I'd like to save a list of selected items from a checkbox list, generated with an angular service as follows.

Unfortunately, my "job" object only persists the state of the last selected checkbox, instead of the id values of all of the selected checkboxes in the list.

Could anyone tell me what am I doing wrong please?

Plunker with the entire example: http://plnkr.co/edit/znLy9EqUMZN6kRzNnl07?p=preview

<script type="text/javascript">
var app = angular.module('helloWorldApp', []);

app.service('HelloWorldService', function() {
  var model = this;
  var people = [{
    "id": 0,
    "firstName": "John",
    "lastName": "Doe",
    "expertise": "Programmer",
    "checked": false
  }, {
    "id": 1,
    "firstName": "Mary",
    "lastName": "Jane",
    "expertise": "Manager",
    "checked": false
  }];

  model.getPeople = function() {
    return people;
  };
});

app.controller('HelloWorldController', ['$scope', 'HelloWorldService',
  function($scope, HelloWorldService) {
    var helloWorld = this;
    // why this does not work?
    // helloWorld.people = function() { return HelloWorldService.getPeople(); };
    // why this one works?
    helloWorld.people = HelloWorldService.getPeople();
    $scope.selectedPeople = [];
    helloWorld.selectedPeople = [];

    $scope.createNewJob = function() {
      console.log("Object: " + JSON.stringify($scope.job));
    };

    $scope.addPerson = function(id) {
      // how can I keep a list of selected people in my ng-model object?
      //helloWorld.selectedPeople.push(id + " selected");
      $scope.selectedPeople.push(id + " selected");
      helloWorld.selectedPeople = $scope.selectedPeople;
      console.log($scope.selectedPeople);
    }
  }
]);

  <tbody ng-controller="HelloWorldController as helloWorld">
    <tr ng-repeat="person in helloWorld.people">
      <td>
        <input type="checkbox" name="peopleList[]" ng-model="job.selectedPeople" ng-click="addPerson(person.id)" value="{{person.id}}" />
        <label>{{person.firstName}} {{person.lastName}}</label>
      </td>
      <td>
        {{person.expertise}}
      </td>
    </tr>
  </tbody>
Pablo
  • 2,054
  • 8
  • 30
  • 56
  • I coded this following the example from http://stackoverflow.com/questions/14514461/how-can-angularjs-bind-to-list-of-checkbox-values – Pablo Jan 14 '15 at 09:40

2 Answers2

1

Currently, the exact same model (job.selectedPeople) is assigned to every row, and the state of the checkbox is added on to the end of selectedPeople every time it's clicked. This means selectedPeople is acting as a history of all clicks, not a record of the current state.

You can use $index to specify that each row in your repeat is modeled on its own array element:

ng-model="selectedPeople[$index]"

You can then remove this because the array will be automatically updated by data binding:

$scope.selectedPeople.push(id + " selected");
helloWorld.selectedPeople = $scope.selectedPeople;

More generally I think it would help to have clearer separation of jobs and people, but hopefully the above will help.

James Waddington
  • 2,894
  • 2
  • 15
  • 24
  • Could you please ellaborate on what could be better about jobs/people? My intent is to create a "new job advertisement" page, where I chose people to apply for the job. So, I am trying to bind the selected values to the "job" model, whereas I need to fetch the info about the people from the "people" service. – Pablo Jan 14 '15 at 10:19
  • Perhaps you could have an array "expertise" so that when creating a job you don't have to select specific people, just the expertise you are looking for. From that expertise array you could build selectors for creating jobs and people, and also use it to create a simple filter for each of those. – James Waddington Jan 14 '15 at 10:32
1

This a running code, your principal mistake was to use an ng-model for each input and it was the controller scope that you could put on the form element.

I use ng-checked directive in order to define if the checkbox has to be checked or not.

  $scope.isChecked = function (id) {
     return $scope.selectedPeople.indexOf(id) > -1;
  }

and html

<input type="checkbox" name="peopleList[]" ng-checked="isChecked(person.id)" ng-click="addPerson(person.id)" />

This is the code, hope that will help you.

http://plnkr.co/edit/jE5fmAGd73c1nGaF5g0C?p=preview

Mathieu Bertin
  • 1,634
  • 11
  • 11