VsM
VsM

Reputation: 890

AngularJS pass $resource as a directive parameter

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.

Upvotes: 4

Views: 3656

Answers (2)

Maxim Shoustin
Maxim Shoustin

Reputation: 77904

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

Upvotes: 5

nordyke
nordyke

Reputation: 113

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

Upvotes: 1

Related Questions