Question

I have just came up with a directive that loads a dropdown box according to a list coming from an API call ($resource).

Controller:

App.controller(
'TestCtrl', [
'$scope', 'countriesFactory',
function($scope, countriesFactory){

        /* Call API */
        countriesFactory().then(function(data){
              $scope.countryList = data;
        });

}])

The API call returns:

{"country":[{"code":"ABW","label":"Aruba"},{"code":"AFG","label":"Afghanistan"},{"code":"AGO","label":"Angola"}]}

Template:

<input-select model-ref-list="countryList"></input-select>

Directive:

App
.directive("inputSelect"
, function() {

    var Template =
        '<select ng-options="item.label for item in modelRefList" required></select>';

    return {
        restrict: 'EA',
        template: Template,
        scope: {
            modelRefList: '='       
        },
        link: function(scope){
          console.log(scope.modelRefList);
        }
      };
   }
);

First of all: I simplified a lot the overall issue, so that it looks that the directive is completely overkill in that situation, but in the end, it is not :D.

Problem: My console.log is always undefined.

I made a bit of research and realized that I needed to play with promises to wait for my country list to appear to be actually given to the directive. So I tried modifying my controller and not use the result of the API call promise, but directly the resource itself:

New Controller:

App.controller(
'TestCtrl', [
'$scope', 'countriesFactory',
function($scope, countriesFactory){

        /* Call API */
        $scope.countryList = resourceAPICall();

}])

But still undefined :/.

How can I pass direclty the resource (containing the promise I can then use to defer the load of the select) to the directive?

SOLUTION FOR ANGULARJS 1.2:

Directive:

App
.directive("inputSelect"
, function() {

    var Template =
        '<select ng-options="item.label for item in modelRefList" required></select>';

    return {
        restrict: 'EA',
        template: Template,
        scope: {
            modelRefList: '='       
        },
        link: function(scope){
           scope.modelRefList.$promise.then(function(data){
                    console.log(data);
           }
      };
   }
);

To pass a API call result to a directive, you need to pass its resource and play with its promise inside the directive itself.

Thanks everybody for the help.

Was it helpful?

Solution

Here we simulated async call factory by using wrapper with $q.

  • We changed modelReflist to modelRefList
  • added ng-model="item" to template

HTML

<div ng-controller="TestCtrl">
    <input-select model-ref-list="countryList"></input-select>    
</div>     

JS

var App = angular.module('myModule', ['ngResource']);

App.controller(
    'TestCtrl', [
    '$scope', 'countriesFactory',

function ($scope, countriesFactory) {
    /* Call API */
    countriesFactory.resourceAPICall().then(function (data) {

        $scope.countryList = data.country;

         console.log($scope.countryList);
    });
}])

App.$inject = ['$scope', 'countriesFactory'];


App.directive("inputSelect", function () {
    var Template = '<select ng-model="item" ng-options="item.label as item.label for item in modelRefList" required></select>';
    return {
        restrict: 'EA',
        template: Template,
        scope: {
            modelRefList: '='
        },
        link: function (scope) {
            console.log(scope.countryList);
        }
    };
});

App.factory('countriesFactory', ['$resource', '$q', function ($resource, $q) {
    var data = {
        "country": [{
            "code": "ABW",
            "label": "Aruba"
        }, {
            "code": "AFG",
            "label": "Afghanistan"
        }, {
            "code": "AGO",
            "label": "Angola"
        }]
    };

    var factory = {
        resourceAPICall: function () {
            var deferred = $q.defer();

            deferred.resolve(data);
            return deferred.promise;
        }
    }
    return factory;
}]);

Demo Fiddle

OTHER TIPS

modelReflist needs to be fully camel-cased in your directive scope. modelRefList.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top