2

I have two pages. One is list and its detail page. Both the page’s data is coming from a single json. I have two controllers for both the pages. I want to use same json in two controllers with a single call. The json structure is something like this:

[
  {
    "tid": "3388",
    "name": "Adagio Bar",
    "description": "Choose to enjoy one of our Italian inspired cocktails while taking in the spectacular views or simply relax.
    "field_location_category": "Aft",
    "category_tid": "351",
    "category_name": "Entertainment/Bars",
    "deck": "Sun Deck 16"
  },
  {
    "tid": "3439",
    "name": "Botticelli Dining Room",
    "description": "A sumptuous variety of dining options awaits you on every voyage.
    "field_location_category": "Aft",
    "category_tid": "350",
    "category_name": "Food and Dining",
    "deck": "Fiesta Deck 6"
  }
 ]

When we press the list page the url like this “list/tid”
How to point out corresponding list to its details?

Controller

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

app.controller("Location", function($scope, $http){<br/>
    $scope.locationList = null;

    $http.get("sites/all/modules/custom/locations/location.json")

        .success(function(data){
            $scope.locationList  = data;

            var indexedloc = [];
            $scope.locationListToFilter = function(){
                indexedloc = [];
                return $scope.locationList; 
            }

            $scope.filterLocation = function(Loc){
                var locationIsNew = indexedloc.indexOf(Loc.category_name) == -1;
                if(locationIsNew){
                    indexedloc.push(Loc.category_name);                 
                }
                return locationIsNew;
            }   
            $scope.returnFilterLoc = function(){return indexedloc};
        })
        .error(function(data) {
            $("div.content").html("Error");
        });
});<br/>

app.controller("LocationDetail", function($scope, $http){
    $scope.locationDetail = null;
    $http.get("sites/all/modules/custom/locations/location.json")
        .success(function(data){
            $scope.locationDetail  = data;
        })<br/>
        .error(function(data) {
            $("div.content").html("Error");
        });
});

I have added html for list page and its detail page in the following link http://jsfiddle.net/cAY2N/14/

Please help. Thanks in advance.

martynas
  • 12,120
  • 3
  • 55
  • 60
Vimal
  • 2,767
  • 3
  • 19
  • 24
  • 4
    You could add a factoryand store the data in the factory. See http://stackoverflow.com/questions/21919962/angular-share-data-between-controllers https://thinkster.io/egghead/sharing-data-between-controllers/ and https://egghead.io/lessons/angularjs-sharing-data-between-controllers Actually, this question has been asked multiple times before here on SO so with a bit of search you could find some great examples – jao Dec 16 '14 at 08:58

2 Answers2

2

As @jao suggested, you could create a factory that returns a promise:

'use strict';

angular.factory('LocationService', ['$q', '$http', function($q, $http) {
  var LocationService = {};

  LocationService.get = function(){
    var deferred = $q.defer();
    $http.get("sites/all/modules/custom/locations/location.json")
      .success(function(data) {
        deferred.resolve(data);
      })
      .error(function() {
        deferred.reject('An error occured while processing the request.');
      });
    return deferred.promise;
  };

  return LocationService;
}]);

So in your controller you would have to inject the LocationService and call it's method get():

var promise = LocationService.get();
promise.then(function(data) {
    // do stuff
}, function() {
    console.log('An error occurred while processing the request.');
});
martynas
  • 12,120
  • 3
  • 55
  • 60
  • 2
    You still have to call twice the promise (one in each controlller). Is there a way of doing it like a singleton (you http get only once)? – MaximeBernard Dec 16 '14 at 09:48
1

Correct answer already mentioned by @jao in comments. However it possibly worth to add one more example. The basic idea is to have a singleton object to store the data. In can be done with factory. This object can be referenced by both controllers and populated only once. Here is the code:

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

// define a singleton object to be used in conrollers
myApp.factory('LocationsData', function() {
    return {
        locations: [],
        current:undefined
    };
});        

function LocationsCtrl($timeout, $scope, LocationsData) {
    $scope.data = LocationsData;
    // perform asynch call, e.g using $http
    $timeout(function() {
        $scope.data.locations = ['First', 'Second'];
        $scope.data.current = $scope.data.locations[0];
    }, 1000);
}

function LocationDetailsCtrl($scope, LocationsData) {
    // just add to scope and wait to be populated
    $scope.data = LocationsData;
}

View:

<div ng-controller="LocationsCtrl">
    <p>Locations List</p>
    <ul>
        <li ng-repeat="location in data.locations">{{location}}</li>
    </ul>
</div>

<div ng-controller="LocationDetailsCtrl">
    <p>Location Details</p>
    {{data.current}}
</div>

Link to JSFiddle

udalmik
  • 7,838
  • 26
  • 40
  • Thank you so much jao, martynas and udalmik for your help and support. Sorry I forgot to say one thing, my two controllers are from two different pages. I have asked one more question in early. How to point out corresponding list to its details? Once again thank you so much for the help. – Vimal Dec 17 '14 at 06:01
  • The approach shown below will work fine with separate views, as single JS object is used to store the information. – udalmik Dec 17 '14 at 10:44