简体   繁体   中英

AngularJS Controller and Directive scope issues

I have been continuing to study angularjs for the past couple of days, especially about directives.

I have a scenario in which I have to load a list of records, with each one of them belonging to a category (5 categories in a drop-down select box). I have created a directive to handle the "change" event for each one of them and made it so that their scopes do not overlap. As you can see on the console logs, each time you select an item from the drop-down, it is independent of the others.

I have two questions:

  1. How do I load the categories ONLY ONCE from an outside resource. To be more specific, I only want to call practiceFactory.getCategories() only once.

  2. Is my code structure on the right track in regards to angular?

Here's my 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>

Here's my 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);
                })
        }
    }
});

Here is a jsfiddle. http://jsfiddle.net/j45fN/

Going to answer your questions backwards...

In response to #2, I don't recommend using a factory to load data in your directive. That sort of logic should take place in your module's controller (not in any directive's controller). In that regard, the other factory calls should be removed from your directive as well.

If you do that, it makes #1 easier -- you can simply call practiceFactory.getCategories once in practiceAppController and pass the result to your directive's scope using a bi-directional binding ( scope: { categories: '=' } ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM