0

I'm trying to create a layout that displays 'channel' data for multiple 'users'. The API I'm using requires one to query first to get a list of username and then another query for each user to get the channel information.

I gave it my best shot but ended up breaking everything with no luck.

Here is a plunker...

HTML:

  <body ng-controller="ChannelCtrl">
    <channel ng-repeat="username in names" data-username="{{ username }}">a</channel>
  </body>

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

app.controller('ChannelCtrl', ['$scope', 'channelService', function($scope, channelService) {
  $scope.names = channelService.getUsers();
}]);

JS:

app.factory('channelService', ['$http', function($http) {
  return {
    getUsers: getUsers,
    getChannel: getChannel
  };

  function getChannel(name) {
    $http.get('api/channels'+name+'Channel.json')
    .success(function(data, status, headers, config) {
      console.log(data);
      return data;
    });
  }

  function getUsers() {
    $http.get('api/users.json')
    .success(function(data, status, headers, config) {
      console.log(data);
      return data;
    });
  }
}]);

app.directive('channel', ['channelService', function(channelService) {
  return {
    restrict: 'E',
    template: "Hello {{ channel }}<br>",
    link: function(scope, element, attrs) {
      scope.channel = channelService.getChannel(attrs.username);
      console.log('channel::link', scope.channel);
    }
  };
}]);
2
  • Describe the problem precisely. "ended up breaking everything with no luck" doesn't tell us anything about what the code is supposed to do and what it does instead. Commented Feb 14, 2015 at 7:03
  • It's not rendering anything, as seen in the plunker. What it should do is fetch the users, then use the list of users to fetch the channel json for each user. Sorry, I've spent an hour on it and don't know how to proceed. Commented Feb 14, 2015 at 7:45

1 Answer 1

1

You have to return your $http.get function in your service. Afterwards to access the data in your controller you must call the $http success function and assign the data response to your scope variable. It is because of the asynchronous behaviour of the $http.get function.

UPDATE

I've updated the plunker so it would show your desired output. You don't have to use attrs in your directive because you can access the scope data from your ng-repeat elements (Scope Chain). If you don't set the scope attribute in your directive definition object this is the default behaviour. I also deleted the unnecessary success function calls in your service as mentioned in the comment.

controller:

app.controller('ChannelCtrl', ['$scope', 'channelService', function($scope, channelService) {
  channelService.getUsers().success(function(users) {
    $scope.users = users; 
  });
}]);

service:

app.factory('channelService', ['$http', function($http) {
  return {
    getUsers: getUsers,
    getChannel: getChannel
};

 function getChannel(name) {
   return $http.get('api/channels/' + name + 'Channel.json');
 }

 function getUsers() {
   return $http.get('api/users.json');
 }
}]);

directive:

app.directive('channel', ['channelService', function(channelService) {
  return {
    restrict: 'E',
    template: "Hello {{ channel }}<br>",
    link: function(scope, element, attrs) {
       channelService.getChannel(scope.user.username).success(function(data) {
       scope.channel = data[0].channel;
     });
  }
};
}]);

Updated Plunker

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

5 Comments

And remove the return data; lines in the success handlers; they do nothing (except confuse people new to promises).
Sorry, I updated the question and part of the code. The element should show the channel's name afterward. Therefore, getChannel should $http.get('api/channels'+name+'Channel.json')
Also, it seems like it'd be an anti-pattern to have .success in the controller. As part of the remote request, shouldn't it all be contained within' the Service?
I updated the code at the same time as you wrote this comment. :) Just have a look at the updated plunker.
You could also wrap your success function call in a callback which is executed when the request is finished. Have a look here. Or you could use the angular $resource service (official tutorial)

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.