Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Plunker

There are a lot of files, so perhaps you Angular aficionados will understand my explanation, or be able to follow the plunker I've provided above.

I'm creating a demo to modularize a webpage. Even the main content of the page will be in another template file. In the main content view, there's a table of links, the link opens an angular-bootstrap modal (another template/controller), which displays additional information for the object clicked.

I'm finding that every time a link is clicked, the factory is retrieving the source data. For something small, it's unnoticeable, but if you're performing an AJAX request to a large dataset, or transforming an XML to JSON, this could take a while. I am uncertain if this is a result of routing, or if it's a poor implementation of what I'm trying to accomplish, but I would like to:

  1. understand why this is happening
  2. retrieve the initial data once and share it between controllers

data.json

[
  {"firstName":"John",
   "lastName":"Denohn",
   "profession":"Student",
   "age":10
  },
  {"firstName":"Mark",
   "lastName":"Fatzigio",
   "profession":"Doctor",
   "age":20
  },
  {"firstName":"Jennifer",
   "lastName":"Cooler",
   "profession":null,
   "age":30
  },
  {"firstName":"Kimberly",
   "lastName":"Branch",
   "profession":"Teacher",
   "age":40
  }
]

index.html

<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
  <head>

    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="myApp.css" rel="stylesheet">

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-route.min.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>

  </head>

  <body>
    <div data-ng-view="" data-ng-cloak ></div>

    <script src="myApp.js"></script>
    <script src="myAppModels.js"></script>
    <script src="myAppControllers.js"></script>
  </body>

</html>

template_initialPageView.html

<div class="page-container" data-ng-cloak>

  <!-- Table Content -->
  <table class="table" data-ng-cloak>
    <thead>
      <tr><th colspan="{{keysToShow.length}}"><h1>People</h1></th></tr>
      <tr><th data-ng-repeat="header in keysToShow">{{ header.displayName }}</th></tr>
    </thead>
    <tbody>
      <tr data-ng-repeat="person in people | orderBy:orderProp">
        <td><a href="#{{[person.firstName, person.lastName].join('_')}}" 
              data-ng-click="showModal(person)"
              >{{ [person.firstName, person.lastName].join(' ') }}</a></td>
        <td>{{ person.profession }}</td>
      </tr>
    </tbody>
  </table>

</div>

template_modalContentView.html

<div class="modal-header">
  <button type="button" class="close" data-ng-click="cancelModal()">&times;</button>
  <h3 class="modal-title" id="myModalLabel">Person Info</h3>
</div>
<div class="modal-body">
  <tabset>
    <tab heading="Age">
      <h4>Name</h4>
      <p>{{ person.firstName + ' ' + person.lastName }}</p>

      <h4>Age</h4>
      <pre>{{ person.age }}</pre>
    </tab>
    <tab heading="Profession">
      <h4>Name</h4>
      <p>{{ person.firstName + ' ' + person.lastName }}</p>

      <h4>Profession</h4>
      <pre>{{ person.profession }}</pre>
    </tab>
  </tabset>
</div>
<div class="modal-footer">
  <button class="btn btn-primary" data-ng-click="closeModal()">Close</button>
</div>

myApp.js

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

/* Routes */
myApp.config(function($routeProvider) {
  $routeProvider
    .when('/home', {
      templateUrl: 'template_initialPageView.html',
      controller: 'PageViewController',
      controllerAs: 'page'
    })
    .otherwise({
      redirectTo: '/home'
    });
});

myAppControllers.js

var myAppControllers = {};

// Define: Page View Controller
myAppControllers.PageViewController = function ($scope, $modal, modelFactory) {

  init();

  function init(){
    $scope.orderProp  = '';
    $scope.keysToShow = [{'displayName':'Fullname'},{'displayName':'Profession'}];
    modelFactory.getPeople().success(function(data){
      $scope.people = data;
    });
  }

  $scope.showModal = function(person) {
    console.log('person clicked', person);
    $scope.person = person;

    var modalInstance = $modal.open({
      controller: 'ModalController',
      controllerAs: 'modal',
      templateUrl: 'template_modalContentView.html',
      resolve: {
        person: function(){
          return $scope.person;
        }
      }
    });

  };

};


// Define: Modal Controller
myAppControllers.ModalController = function ($scope, $modalInstance, person) {
  init();

  function init(){
    $scope.person = person;
  }

  $scope.cancelModal = function (){
    $modalInstance.dismiss('cancel');
  };

  $scope.closeModal = function () {
    $modalInstance.close();
  };

};


// Add controlers to the module
myApp.controller(myAppControllers);

myAppModels.js

myApp.factory('modelFactory', function($http){
  var factory = {};

  factory.getPeople = function (){
    return $http.get('data.json');
  };

  return factory;

});
share|improve this question
add comment

1 Answer

You can try this, it initially returns an empty array that will be populated when $http.get() returns and it re-uses the array each time it is called:

myApp.factory('modelFactory', function($http){
  var factory = {};

  factory.getPeople = function () {
    if (typeof(factory.people) == "undefined") {
      factory.people = [];
      $http.get('data.json').success(function(result) {
        var i = 0;
        for (i = 0; i < result.length; i++) {
          factory.people.push(result[i]);
        }
      });
    }
    return factory.people;
  };

  return factory;

});
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.