Constellates
Constellates

Reputation: 2113

How can I dynamically set templates without messy query parameters in angular ui-router?

I'm building an artist portfolio web app where the artist can create a 'project' which consists of a series of content pieces (mostly images at this point) which can then be put in an order and the artist can choose between different preset layouts. I'm using angular and node + express. I'm struggling to find a good way to dynamically set templates. The only functional scheme i've devised so far is to put the template name in a query parameter in the url like this.

ui-sref="webapp/project/photo?template=vertical"

then in ui-router it's relatively simple to set the template using state params

templateUrl : function (stateparams) {
  return 'templates/' + stateparams.template + '.html';
},

Although it's functional I don't like this mostly because it creates messy urls and allows anyone to change templates with query params or more likely load something without a real template because the url was typed incorrectly or correctly without the query parameter.

I can't make an api call from the templateUrl function because it's not injectable so I can't use the $http service. I've tried to use template provider but haven't made anything functional out of that yet. It does allow for an injectable function but that function must return an entire template instead of a url. If I can get a template url for it how can a load the template with that? I assume I'm not the first person to want dynamic templates (templates set in the database) from angular. What are my best options?

Upvotes: 0

Views: 629

Answers (2)

Constellates
Constellates

Reputation: 2113

I have found a functional solution to my problem using ui-router, $stateParams, and $http. I'll be looking for a better architecture scheme as this necessitates 3 server requests every time a project is requested. One to get the template name and another to load the template file and another to load the project data. I suppose I only added one request to the norm. Anyways.. This solution is working for me but next I will be moving the logic to get template by the project name to an angular service to keep everything clean.

.state('projects/:project_url', {
  url              : '/projects/:project_url',
  templateProvider : function ($stateParams, $http) {
    return $http.get('/api/projects/' + $stateParams.project_url)
      .then(function (data) {
        // get template name
        var templateName = data.data[0].template;
        // return template by name
        return $http.get('/pages/' + templateName + '.html')
          .then(function (data) {
            return data.data;
          });
      });
  },
  controller       : 'projectCtrl'
});

Upvotes: 1

Jens
Jens

Reputation: 3412

http://dotjem.github.io/angular-routing/ supports your scenario with inject-able template functions. Note however that you must provide the raw template in the return statement, but that is easily done using the $template service...

It is very similar to UIRouter, so it should be a fairly easy transition if you find it worth it.

http://plnkr.co/edit/dkPIWMW236ixifETohNW?p=preview

If you take the latest stable release rather than the head you must add a "get" call to that service as: $template.get('template.html') rather than the newer: $template('template.html')

Upvotes: 0

Related Questions