I have one controller that gets an object with albums from facebook api.
.controller('GalleryCtrl', function($scope, $http) {
$http.get('https://graph.facebook.com/v2.0/130180763686565/albums?fields=id,type,name,cover_photo,description&access_token=TOKEN').
success(function(datos) {
$scope.galleries = datos.data;
})
})
In my view I print it like this,
<div ng-app="faceBook">
<div class="list" ng-repeat="gallery in galleries" ng-if="gallery.type=='normal'">
<a class="item item-thumbnail-left" href="#/app/gallery/{{gallery.id}}" ng-click="$rootScope.albumId = {{gallery.id}}">
<img src="https://graph.facebook.com/{{gallery.id}}/picture?type=album">
<h2>{{gallery.name}}</h2>
<p>{{gallery.description}}</p>
</a>
</div>
What I need is to asign every Album the ID of the object (gallery.id) and send it to the next controller, to be able to download the pictures of that album.
Send the gallery.id to this controller to put hte varible inside the http.get shown below where albumId is.
How can I send the variable of the item clicked, from the first controller to the second?
This is my Single Album Controller
.controller('AlbumCtrl', function($scope, $http) {
$http.get('https://graph.facebook.com/v2.0/'+albumId+'/photos?fields=id&access_token=TOKEN').
success(function(datos) {
$scope.albums = datos.data;
})
})
There are different opinions about how to do this, as there are several approaches. Let me outline them briefly for you. I would primarily use a service, then $rootScope, and lastly events.
Use services
Services are Javascript objects that can be passed around using Angular's dependency injection. Just like you can request $http in your controller, you could create a service that would be able to exist anywhere DI works. This is the best approach (IMO) because you isolate your data into the service and are able to use DI to pass it around easily. The object doesn't have to just contain data, it can have methods which can reduce code duplication. The only negative I can think of is having create a new file.
This example is not ideal or work in all situations, you should adapt it as necessary. This example is only able to load the albums once when the service is first injected, and stores the data for any to use. Generally I make more complex services that can manage the data so my controllers don't have to manipulate my models.
Service
angular.module('App').factory('AlbumService', function ($http) {
var AlbumService;
// Make our $http request and assign response to service
$http.get('https://graph.facebook.com/v2.0/1234567890/albums?fields=id,type,name,cover_photo,description&access_token=TOKEN')
.success(function(response) {
AlbumService = response.data;
});
};
return AlbumService;
});
Controller 1
angular.module('App').controller('OneCtrl', function ($scope, AlbumService) {
// Assume this runs first, it will create the service and make the http
// request and be made available to the $scope
$scope.albums = AlbumService;
});
Controller 2
angular.module('App').controller('TwoCtrl', function ($scope, AlbumService) {
// Assume this runs second, it will return the same data from above.
// Even if it runs first, the result is the same because the first to inject
// the AlbumService will execute the $http request once and reuse the data
console.log(AlbumService);
});
Use $rootScope to share
You can assign anything to $rootScope
and get to it from any controller, directive, service, and most places (a few exceptions like app.config). This is handy and requires very little overhead. On the flip side, it kinda abuses your $rootScope and if you happen to use the same property name on $scope elsewhere you can have values get lost or overridden unintentionally.
Controller 1
angular.module('App').controller('OneCtrl', function ($rootScope, $http) {
$http.get('https://graph.facebook.com/v2.0/1234567890/albums?fields=id,type,name,cover_photo,description&access_token=TOKEN')
.success(function(response) {
$rootScope.items = response.data;
});
});
Controller 2
angular.module('App').controller('TwoCtrl', function ($scope) {
// will log out the values from response.data above, since its not on
// $scope it travels up the scope tree until the $rootScope.
console.log($scope.items);
});
Custom events
You can use events to broadcast (down the scope tree) or emit (up the scope tree) data. It's conceptually the same idea as listening to the domready
event before you use JavaScript. The benefits are you don't use $rootScope
and you can control if you send data up or down the scope tree (depending on what scopes need to know about this data). On the other hand, events can be tricky and cause confusion about causality as well as creating a dependency between various parts of the application that can make it difficult to maintain. In this example, both controllers also have to be in the same page for both the $broadcast and $on to be active.
Opinion: I would avoid this approach in most cases. One example where it might work is if you have a custom directive controlling an outside library (such as a chart) and you need to trigger the chart to change when events occur. I would use it when you need event driven, which is different from the original question about how to access data in different controllers (I would call that model driven).
Controller 1
angular.module('App').controller('OneCtrl', function ($rootScope, $http) {
// This will broadcast this event down through every scope from the top
$http.get('https://graph.facebook.com/v2.0/1234567890/albums?fields=id,type,name,cover_photo,description&access_token=TOKEN')
.success(function(response) {
$rootScope.$broadcast('myCustomEvent', response.data);
});
});
Controller 2
angular.module('App').controller('TwoCtrl', function ($scope) {
// will log out the value of response.data above when the $broadcast occurs
$scope.$on('myCustomEvent', function (event, data) {
console.log(data);
});
});
You should provide more information about your problem:
From what I understand this is what you are trying to do.
Change your href call to ng-href and remove the ng-click.
This:
<a class="item item-thumbnail-left" href="#/app/gallery/{{gallery.id}}" ng-click="$rootScope.albumId = {{gallery.id}}">
Becomes this
<a class="item item-thumbnail-left" ng-href="/app/gallery/{{gallery.id}}">
In the controller that will deal with the view. Suppose you'll call it ViewAlbumCtrl.
.controller('ViewAlbumCtrl', function($scope, $http, $routeParams) {
var theId = $routeParams.galleryId;
//Your cool code
});
And where you configure your routes you should have:
.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/app/gallery/:galleryId', {
templateUrl: '/path/to/your/view.html',
controller: 'ViewAlbumCtrl'
});
}]);
Hope it helps you.
Use $stateParams!
In your app.js file
.state('app.single', {
url: "/clientes/:clienteId",
views: {
'menuContent': {
templateUrl: "views/cliente.html",
controller: 'ClienteCtrl'
}
}
})
Inside your view:
<ion-item class="item-avatar" href="#/app/clientes/{{cliente.id}}" >
The controller:
angular.module('cobranza-mobile.controllers').
controller('ClienteCtrl', function ($scope, $stateParams) {
alert($stateParams.clienteId);
});
You can send a message at $rootScope level from controller A and intercept it in controller B.
Inject $rootScope service into controller A.
Broadcast the message and parameter[s] from controller A:
$rootScope.$broadcast('userDefinedEvent', {parameterOne: 'stringValue'});
Intercept it in controller B and take action accordingly:
$scope.$on('userDefinedEvent', function (event, data) {
console.log(data);
});
Hope it'd help you.
Cheers, Luca