Angular-UI-Router - getting content of dynamic tem

2019-04-27 12:06发布

问题:

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.

回答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;
      })


回答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.