문제

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;

});
도움이 되었습니까?

해결책

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;

});

And don't forget to change your assignment to accept an array and just use that:

$scope.people = modelFactory.getPeople();

(PLUNKR)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top