angularjsautocompleteangular-templatecache

$templateCache from file undefined? When is the accessible by other js code? (with np-autocomplete)


I'm rather new to angular and I'm trying to integrate np-autocomplete in my application (https://github.com/ng-pros/np-autocomplete). However I can only get it to work when I'm passing a html string as a template inside the $scope.options and it doesn't work when I want to load it from a separate html.

the Code for my app looks as follows:

var eventsApp = angular.module('eventsApp',['ng-pros.directive.autocomplete'])

eventsApp.run(function($templateCache, $http) {
    $http.get('test.html', {
      cache: $templateCache
    });
   console.log($templateCache.get('test.html'))  // --> returns undefined

   setTimeout(function() {
       console.log($templateCache.get('test.html'))  // --> works fine
   }, 1000);

   //$templateCache.put('test.html', 'html string') //Would solve my issue in the controller,
   //but I would rather prefer to load it from a separate html as I'm trying above

Inside my controller I am setting the options for autocomplete as follows:

controllers.createNewEventController = function ($scope) {
    $scope.options = {
        url: 'https://api.github.com/search/repositories',
        delay: 300,
        dataHolder: 'items',
        searchParam: 'q',
        itemTemplateUrl: 'test.html',  // <-- Does not work  
    };
    //other stuff...
}

however, it seems that test.html is undefined by the time np-autocomplete wants to use it (as it is also in first console.log above).

So my intuition tells me that the test.html is probably accessed in the controller before it is loaded in eventsApp.run(...). However I am not sure how to solve that?

Any help would be highly appreciated.


Solution

  • You are most likely correct in your assumption.

    The call by $http is asynchronous, but the run block will not wait for it to finish. It will continue to execute and the execution will hit the controller etc before the template has been retrieved and cached.

    One solution is to first retrieve all templates that you need then manually bootstrap your application.

    Another way that should work is to defer the execution of the np-autocomplete directive until the template has been retrieved.

    To prevent np-autocomplete from running too early you can use ng-if:

    <div np-autocomplete="options" ng-if="viewModel.isReady"></div>
    

    When the template has been retrieved you can fire an event:

    $http.get('test.html', {
      cache: $templateCache
    }).success(function() {
      $rootScope.$broadcast('templateIsReady');
    });
    

    In your controller listen for the event and react:

    $scope.$on('templateIsReady', function () {
    
      $scope.viewModel.isReady = true;
    });
    

    If you want you can stop listening immediately since the event should only fire once anyway:

    var stopListening = $scope.$on('templateIsReady', function() {
    
      $scope.viewModel.isReady = true;
      stopListening();
    });