0

I have two json files being requested for two differents angularjs services.

  • /people.json
    • {user-name, user-id}
  • /task.json
    • {name-task, task-id, responsible-id}
Where responsible-id = user-id.

I can pass an ID parameter to the task json to request all the task for the user with that ID: /task.json?ID=12

I'm trying to create a nested ng-repeat, the first one to get all the users in /people.json, the second to get all the task for each user in the loop but i ended up with something like this: https://i.stack.imgur.com/P2YZp.png

The first ng-repeat shows correctly the different users, but the second show the same tasks of the first user to the others users in the list.

¿How can i change the parameter to update correctly for the nested ng-repeat?

My Services:

    .service('TeamworkPeopleSrvc', function($http, $q){
      var deferred = $q.defer();
      var TeamworkPeopleSrvc = this;
      TeamworkPeopleSrvc.getPeople = function(){
        $http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
        $http({
          method: 'GET',
          url: 'http://projects.com/people.json',
          params: { 'pageSize':'5'},
        })
        .then(function(response) {
          deferred.resolve(response);
        });
          return deferred.promise;
      };
      return TeamworkPeopleSrvc;
    })
  .service('TeamworkTasksSrvc', function($http, $q){
      var deferred = $q.defer();
      var TeamworkTasksSrvc = this;
      TeamworkTasksSrvc.getTasks = function(id){
        $http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
        $http({
          method: 'GET',
          url: 'http://projects.com/tasks.json' ,
          params: { 'id':id, 'getSubTasks':'no', 'pageSize':'10'},
        })
        .then(function(response) {
          deferred.resolve(response);
        });
          return deferred.promise;
      };
      return TeamworkTasksSrvc;

    })

My Controller

.controller('PeopleCtrl', function ($scope, TeamworkPeopleSrvc, TeamworkTasksSrvc) {
  $scope.init = function(){
    $scope.peopleObjects();
  };

  $scope.taskObjects = function(id){
    TeamworkTasksSrvc.getTasks(id)
    .then(function(response){
      $scope.userTasklist = response.data['todo-items'];
    });
  };

  $scope.peopleObjects = function(){
    TeamworkPeopleSrvc.getPeople()
    .then(function(response){
      $scope.userlist = response.data.people;
    });
  };

  $scope.init();
});

and try to init the tasks with the updated user id in the template

  <div ng-controller="PeopleCtrl">
    <div ng-repeat="person in userlist">
      <h3>{{person['id']}} | {{person['first-name']}} {{person['last-name']}}</h3>

      <div ng-init="taskObjects(person['id'])">
        <div ng-repeat="task in userTasklist">
        {{task['responsible-party-id']}} - {{task['content']}}
        </div>
      </div>
    </div>
  </div>

Best Regards.

2 Answers2

1

The problem is in your controller code. You are using the same $scope for both loops, which means that each time you call taskObjects(), you are overwritting $scope.userTasklist with a new task list. You should either establish a new scope for each instance within the loop, or you should make $scope.userTasklist an object with properties matching the person.id.

In your controller change:

  $scope.taskObjects = function(id){
    TeamworkTasksSrvc.getTasks(id)
    .then(function(response){
      if(!$scope.userTasklist) {
         $scope.userTasklist = {};
      }
      $scope.userTasklist[id] = response.data['todo-items'];
    });
  };

And then in your view use:

  <div ng-controller="PeopleCtrl">
    <div ng-repeat="person in userlist">
      <h3>{{person['id']}} | {{person['first-name']}} {{person['last-name']}}</h3>

      <div ng-init="taskObjects(person['id'])">
        <div ng-repeat="task in userTasklist['id']">
        {{task['responsible-party-id']}} - {{task['content']}}
        </div>
      </div>
    </div>
  </div>
BayssMekanique
  • 894
  • 1
  • 14
  • 27
  • After i update the controller and the view i get an `Cannot set property 'id' of undefined`. – Angel Yarmas Apr 18 '16 at 13:40
  • Sorry, you will need to declare `userTasklist` as an object. There might be a better place to do this, but you can do it inside your `getTasks` method. – BayssMekanique Apr 18 '16 at 14:45
0

Defective $q.defer Anti-Pattern1

.service('TeamworkPeopleSrvc', function($http, $q){
  var deferred = $q.defer();
  var TeamworkPeopleSrvc = this;
  TeamworkPeopleSrvc.getPeople = function(){
    $http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
    $http({
      method: 'GET',
      url: 'http://projects.com/people.json',
      params: { 'pageSize':'5'},
    })
    .then(function(response) {
      deferred.resolve(response);
    });
      return deferred.promise;
  };
  return TeamworkPeopleSrvc;
})

Both services in the code use a defective $q.defer Anti-Pattern. With the deferred object created outside the .getPeople function, the promise will only be resolved once with the first resolve. Subsequent resolves are ignored and the promise always returns the first value. In addition if the XHR has an error, the error information is lost. With errors, the promise never resolves or resolves only with the first fulfilled XHR.

Implemented Without $q.defer

.service('TeamworkPeopleSrvc', function($http, $q){
    var TeamworkPeopleSrvc = this;
    TeamworkPeopleSrvc.getPeople = function(){
        var authHeader = { Authorization: 'Basic ' +
              window.btoa('mycustomapikey' + ':' + 'X')
        };
        var httpPromise = ($http({
            method: 'GET',
            url: 'http://projects.com/people.json',
            headers: authHeader,
            params: { 'pageSize':'5'},
            })
        );
        return httpPromise;
    };
    return TeamworkPeopleSrvc;
});

To implement the service correctly, simply return the promise returned by the $http service. A new promise will be created each time the $http function is invoked and error information will be properly retained.

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95