Search code examples
angularjsangular-promiseangular-directive

Angularjs: directive sees its scope but it's not able to take a single variable in it


I am becoming crazy because of a strange behaviour of a directive. It's a quite standard one, and it gets parameters that are provided from DB. Of course the data from DB are token using a promise:

//opening of directive and definition of controller
   return {
        restrict: 'EA',
        scope: {
            dateFromPromise: '=',  //a Date() object
            timeFromPromise: '=',  //a Date() object
            booleanFromPromise '='
        },
        templateUrl: 'abc/abc.html',
        controller: AController,
        controllerAs: 'aController'
    };
 //closing of directive

Now, some variables are not seen, even if both come from the same promise.

If i try to print $scope.booleanFromPromise it's fine, but I cannot print $scope.dateFromPromise and $scope.timeFromPromise (undefined). Maybe because it needs more time to be created?

If I run a browser with F12, I see in console the following as result of console.log($scope); everything is defined and correct, as i wish:

$scope:
n {
    ...
    booleanFromPromise: true
    dateFromPromise: Date {Tue May 24 2016 10:12:00 GMT+0200 (Central European Standard Time)}
    timeFromPromise: Date {Tue May 24 2016 10:12:00 GMT+0200 (Central European Standard Time)}
}

so the dates are present and correct, at least when I print by console in this unlogical language that is js.

How to do in order to:

  1. get all the data from the promise
  2. only after step 1. is complete, pass the data to the tag with directive, that will see everything.
  3. Understand why the directive sees all variables in its own scope, but it's not able to take a single date in it, even if set.

Thanks


Solution

  • There are a couple of things you can do.

    First of all, use a watch in your directive as @Jacky Coogan suggests, that way you will be able to see when the models change.

    Secondly, you said that you get all your data from the promise, so you can do something like this:

    res.$promise.then(function (data) {
                    deffered.resolve(data);
                    $scope.dataLoaded = true;
                });
    

    and then in your html, where you are using your directive, put something like this

    <div ng-if="dataLoaded">
       <your-directive booleanFromPromise="xxx" dateFromPromise="yyy" timeFromPromise="zzz" ></your-directive>
    </div>
    

    this way, you will be able to make sure your directive is initialized with already loaded data.

    Alternatively, instead of the method above, you can use a "controllerResolver", to make sure your data is loaded as controller is initialized, then you won't need the $scope.dataLoaded. For example something like this:

    app.factory("someControllerResolver", ["someService",function (someService) {
    
           return {
                resolve: function () {
                    var deferred = $q.defer();
    
                    someService.getSomething({}, function (res) {                        
                        deferred.resolve(res.data);
                    });
    
                    return deferred.promise;
                }
            };
    
            return {
                resolve: resolve
            };
    
        }]);
    
        app.controller("someController", ["dataContext",function (dataContext) {
            $scope.yourData = dataContext;
        ...
    

    Try one of the methods above, and then your directive should load your data correctly.

    If not, then dig into what's returned from the server. If data returned from the server is OK, then maybe you made a mistake on how you are passing values to your directive.

    Hope this helped.