[javascript] In Angular, how to pass JSON object/array into directive?

Currently, my app has a controller that takes in a JSON file then iterates through them using "ng-repeat". This is all working great, but I also have a directive that needs to iterate through the same JSON file. This is posing a problem as I cannot request the same JSON file twice on one page (nor would I want to because it would be inefficient). Both the directive and controller request and iterate through the JSON data just fine if I change the filename of one of the JSON files.

What I'm wondering is: what's the best way to go about passing the array formed from my controller's JSON request into the directive? How can I pass the array into my directive and iterate through when I've already accessed it via my controller?

Controller

appControllers.controller('dummyCtrl', function ($scope, $http) {
   $http.get('locations/locations.json').success(function(data) {
      $scope.locations = data;
   });
});

HTML

<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map></map> //executes a js library

Directive (Works when I use a file name besides locations.json, since I've already requested it once

.directive('map', function($http) {
   return {
     restrict: 'E',
     replace: true,
     template: '<div></div>',
     link: function(scope, element, attrs) {

$http.get('locations/locations.json').success(function(data) {
   angular.forEach(data.locations, function(location, key){
     //do something
   });
});

The answer is


What you need is properly a service:

.factory('DataLayer', ['$http',

    function($http) {

        var factory = {};
        var locations;

        factory.getLocations = function(success) {
            if(locations){
                success(locations);
                return;
            }
            $http.get('locations/locations.json').success(function(data) {
                locations = data;
                success(locations);
            });
        };

        return factory;
    }
]);

The locations would be cached in the service which worked as singleton model. This is the right way to fetch data.

Use this service DataLayer in your controller and directive is ok as following:

appControllers.controller('dummyCtrl', function ($scope, DataLayer) {
    DataLayer.getLocations(function(data){
        $scope.locations = data;
    });
});

.directive('map', function(DataLayer) {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function(scope, element, attrs) {

            DataLayer.getLocations(function(data) {
                angular.forEach(data, function(location, key){
                    //do something
                });
            });
        }
    };
});

As you say, you don't need to request the file twice. Pass it from your controller to your directive. Assuming you use the directive inside the scope of the controller:

.controller('MyController', ['$scope', '$http', function($scope, $http) {
  $http.get('locations/locations.json').success(function(data) {
      $scope.locations = data;
  });
}

Then in your HTML (where you call upon the directive).
Note: locations is a reference to your controllers $scope.locations.

<div my-directive location-data="locations"></div>

And finally in your directive

...
scope: {
  locationData: '=locationData'
},
controller: ['$scope', function($scope){
  // And here you can access your data
  $scope.locationData
}]
...

This is just an outline to point you in the right direction, so it's incomplete and not tested.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?

Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature

Examples related to angularjs-directive

Angular2 - Input Field To Accept Only Numbers Use of symbols '@', '&', '=' and '>' in custom directive's scope binding: AngularJS ng-change not working on a text input Controller not a function, got undefined, while defining controllers globally Find child element in AngularJS directive Angular directives - when and how to use compile, controller, pre-link and post-link How to validate email id in angularJs using ng-pattern Enable/Disable Anchor Tags using AngularJS get original element from ng-click How to detect browser using angularjs?

Examples related to angularjs-ng-repeat

Angular ng-repeat add bootstrap row every 3 or 4 cols ng-if, not equal to? Understanding the ngRepeat 'track by' expression Calculating sum of repeated elements in AngularJS ng-repeat Angular.js ng-repeat filter by property having one of multiple values (OR of values) Using ng-if as a switch inside ng-repeat? In Angular, how to pass JSON object/array into directive? how to split the ng-repeat data with three columns using bootstrap Preserve line breaks in angularjs ng-repeat: access key and value for each object in array of objects