AngularJS控制器和指令范围问题

问题描述:

过去几天我一直在继续研究angularjs,尤其是关于指令。AngularJS控制器和指令范围问题

我有一个场景,我必须加载一个记录列表,每个记录属于一个类别(5个类别在下拉选择框中)。我已经创建了一个指令来处理它们中的每一个的“更改”事件,并使它们的范围不重叠。正如您在控制台日志中所看到的,每次从下拉列表中选择一个项目时,它都是独立于其他项目的。

我有两个问题:

  1. 如何从外部资源只有一次加载的类别。到 更具体一些,我只想调用 practiceFactory.getCategories()一次。

  2. 是我的代码结构在正确的轨道方面?

这里是我的html:

<div data-ng-app="practiceApp"> 
    <h1>practiceAppController</h1> 
    <div data-ng-controller="practiceAppController"> 
     <p><select data-when-changed="saveCategory({{selectedCategoryId}})" data-ng-model="selectedCategoryId" data-ng-options="category.id as category.name for category in categories"></select></p> 
     <p><select data-when-changed="saveCategory({{selectedCategoryId}})" data-ng-model="selectedCategoryId" data-ng-options="category.id as category.name for category in categories"></select></p> 
     <p><select data-when-changed="saveCategory({{selectedCategoryId}})" data-ng-model="selectedCategoryId" data-ng-options="category.id as category.name for category in categories"></select></p> 
     <p><select data-when-changed="saveCategory({{selectedCategoryId}})" data-ng-model="selectedCategoryId" data-ng-options="category.id as category.name for category in categories"></select></p> 
     <p><select data-when-changed="saveCategory({{selectedCategoryId}})" data-ng-model="selectedCategoryId" data-ng-options="category.id as category.name for category in categories"></select></p> 
    </div> 
</div> 

这里是我的JS:

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

practiceApp.controller('practiceAppController', function($scope, practiceFactory) { 
}); 

practiceApp.factory('practiceFactory', function() { 
    var factory = {}; 

    factory.getCategories = function() { // async call here 
     console.log('getCategories() was called'); 
     var categories = [ 
      {id: 1, name: 'Food & Dining'}, 
      {id: 2, name: 'Hotel & Travel'}, 
      {id: 3, name: 'Shopping'}, 
      {id: 4, name: 'Health & Beauty'}, 
      {id: 5, name: 'Activities'} 
     ]; 
     return categories; 
    } 

    factory.getSelectedCategory = function() { // async call here 
     console.log('getSelectedCategory() was called'); 
     var selectedCategoryId = Math.floor((Math.random()*5)+1); 
     return selectedCategoryId; 
    } 

    return factory; 
}); 

practiceApp.directive('whenChanged', function(practiceFactory) { 
    return { 
     restrict: 'A', 
     scope: {}, 
     controller: function ($scope) { 
      $scope.selectedCategoryId = practiceFactory.getSelectedCategory(); 
      $scope.categories = practiceFactory.getCategories(); 

      $scope.saveCategory = function(categoryId) { 
       console.log(categoryId); 
      } 
     }, 
     link: function(scope, element, attribute) { 
       element.bind('change', function() { 
        scope.$apply(attribute.whenChanged); 
       }) 
     } 
    } 
}); 

这里是一个的jsfiddle。 http://jsfiddle.net/j45fN/

要倒退为您解答...

在回答#2,我不建议使用工厂在你的指令来加载数据。这种逻辑应该发生在你的模块的控制器中(不在任何指令的控制器中)。在这方面,其他工厂电话也应该从您的指令中删除。

如果你这样做,它使#1更容易 - 你可以简单地在practiceAppController调用practiceFactory.getCategories一次,并使用结果传递给你的指令的范围双向绑定(scope: { categories: '=' })。

+0

谢谢你的回答。是的,我必须将数据加载到我的指令中才能解决我遇到的范围问题。我已经按照您的建议尝试过,但不知何故无法实现。下拉列表未被填充。如果您如此友善地编辑我上面的小提琴链接以显示正确的方式?非常感谢你。 – lynkyle

+0

我想我不明白这个指令的必要性。这似乎是一个更干净的方式来做到这一点,除非我失踪:something.http://jsfiddle.net/j45fN/1/ – Langdon

+0

哇!谢谢。为了更多地了解指令,我忽略了一些简单的事情,并开始重新发明*。只是一个后续问题,$ index是从哪里来的? (.i.e。data-ng-model =“selectedCategories [$ index]”) – lynkyle