Angular-UI-Router – getting content of dynamic template

All we need is an easy explanation of the problem, so here it is.

I am building an angular app using angular-ui-router. The backend has a REST api that gives me the url to a form based on a ticket id. In app.js, I want to dynamically set the template based on a query to this REST service. Example:

$stateProvider
  .state('form', {
    url: '/form/:id',
    templateProvider: function ($resource, formResolver, $stateParams) {

      //formResolver calls the REST API with the form id and gets back a URL.
      return formResolver.resolve($stateParams.id).then(function(url) {
        return $resource(url).get();
      };

    },
    controller: 'MyCtrl'
  });

The problem is that I end up returning a promise and templateProvider requires a string of content. What I would like to do is just return the url:

$stateProvider
  .state('form', {
    url: '/form/:id',

    //I would like to inject formResolver, but I can't
    templateUrl: function (stateParams, formResolver) {
      return formResolver.resolve(stateParams.id);
    },
    controller: 'MyCtrl'
  });

But I don’t get dependency injection when using templateUrl instead of templateProvider as per https://github.com/angular-ui/ui-router/wiki#wiki-templates, and I still have the problem of it returning a promise. I am thinking maybe my only solution is not to use the promise api.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Turns out there was something wrong with the way I was using $resource. I’m still not sure what. From looking at the source for angular-ui-router, the function can return a promise. I ended up copying some of the code from https://github.com/angular-ui/ui-router/blob/master/src/templateFactory.js to get the following, which works:

    templateProvider: function ($http, formService, $stateParams) {
      return formService.getFormUrl($stateParams.id).then(function(url) {
        return $http.get(url);
      }).then(function(response) {
        return response.data;
      })

Method 2

Function for templateProvider may return promise from $resource but in the end it has to return string.

templateProvider: function (SomeService) {

    var promise = SomeService.get().$promise;

    promise.then(function (data) {
        console.log(data) // it has to be string!
    });

    return promise; 
}

If there is an object one of the solutions would be to make another promise.

templateProvider: function (SomeService, $q) {

    var defer = $q.defer();

    var promise = SomeService.get().$promise;

    promise.then(function (data) {
        console.log(data) // let say this is {html: '<p>some template</p>'}
        defer.resolve(data.html);
    });

    return defer.promise; 
}

SomeService returns $resource.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply