5

What I have done. I retrieve a list of videos from youtube api with json in a controllerA with specific directive. The json contain the list of video and the video itself details.

What I want to do. When click on a video, I want the video's details display in another ng-view with other controllerB with using the json data I request before.

So my question is How to pass the data from controllerA to controllerB

Note - $http service is use in controllerA

vzhen
  • 10,891
  • 13
  • 51
  • 82

1 Answers1

15

This is one of the common doubts when starting with AngularJS. By your requirement, I believe your best option is to create a service that retrieves the movie list and then use this service in both controllerA and controllerB.

module.factory('youtube', function() {
  var movieListCache;

  function getMovies(ignoreCache) {
    if (ignoreCache || !movieListCache) {
      movieListCache = $http...;
    }

    return movieListCache;
  }

  return {
    get: getMovies
  };
});

Then you just inject this service in both controllers.

module.controller('controllerA', ['youtube', function(youtube) {
  youtube.get().then(function doSomethingAfterRetrievingTheMovies() {
  });
}]);

module.controller('controllerB', ['youtube', function(youtube) {
  youtube.get().then(function doAnotherThingAfterRetrievingTheMovies() {
  });
}]);

If you need controllerA to manipulate the info before you use it in B then you could create more methods in the service. Something like this:

module.factory('youtube', function($q) {
  var movieListCache,
      deferred = $q.defer();

  function getMovies(ignoreCache) {
    if (ignoreCache || !movieListCache) {
      movieListCache = $http...;
    }

    return movieListCache;
  }

  function getChangedMovies() {
    return deferred.promise;
  }

  function setChangedMovies(movies) {
    deferred.resolve(movies);
  }

  return {
    get: getMovies,
    getChanged: getChangedMovies,
    setChanged: setChangedMovies
  };
});

If you don't know what $q is, take a look at the docs. This is mandatory to handle async operations.

Anyway, there are some other ways of accomplishing this task too:

  1. You could save the videos at $rootScope
  2. If the controllers are father and son the you could use require to retrieve each other controller

IMHO, #1 is a generic solution; I'd use it only if there is no other option. And #2 is useful if you have an intrinsic need to communicate between these controllers, such as configuring or letting one know about the other's existence. There is a example here.

What you want to do is to share stateful singleton information; therefore, a service is the way to go.

whyceewhite
  • 5,889
  • 7
  • 41
  • 50
Caio Cunha
  • 23,016
  • 6
  • 74
  • 73
  • i read the official documentation and there is a factory(). Can you make a quick explaination about using factory() and without it? Thank you. – vzhen Apr 03 '13 at 04:15
  • They all expose services to the module. The difference resides in its the sofistication level. While provider is the most sofisticated, even allowing decoration, and service is the most straight forward. There are good explanations and example [here](https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ), [here](https://groups.google.com/d/msg/angular/56sdORWEoqg/-TgFGhm4NYAJ), [here](http://stackoverflow.com/a/13763886/179138), and [here](http://jsfiddle.net/pkozlowski_opensource/PxdSP/14/). If you still don't understand, call me to a chat and I'll explain you. Fixed my code. – Caio Cunha Apr 03 '13 at 12:30
  • Hi, I got understand that creating a service. But i think my problem is not about linking between controller. Do you free to chat now? btw, how to chat in stackoverflow? – vzhen Apr 03 '13 at 13:14
  • @CaioToOn, it looks like I don't get this answer. Imagine you have a select build on top of data fetched remotely - let's say, it is a list of movies. Now some other controller deals with data fetched for a specific movie from that list. As far as I understand your advise is to have a separate place (service) for fetching and caching list of movies. But I don't get how it helps to build second view. – shabunc Feb 10 '14 at 17:01
  • Hi @shabunc. My understanding of the question would be that he wants to use the same JSON array in both controllers. In your case, what you need to do is to: a) expose the clicked value in a service property (`youtube.selected = ...`) and reuse it in the controller (`$scope.selected = youtube.selected`); or b) make use of ng-route and pass along IDs that should be refetched from the server. – Caio Cunha Feb 11 '14 at 15:17