Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

templateUrl with function, hardcoded $element and $attrs #13526

Closed
poshest opened this issue Dec 13, 2015 · 6 comments
Closed

templateUrl with function, hardcoded $element and $attrs #13526

poshest opened this issue Dec 13, 2015 · 6 comments

Comments

@poshest
Copy link
Contributor

poshest commented Dec 13, 2015

I'm trying to use an element

<comp tplsuffix="{{user.lang}}"></comp>

and in the .component definition use the function form of templateUrl to add the tplsuffix to the end of the template url, thus

bindings: {
       "tplsuffix": '='
    },
 templateUrl: function ($element, $attrs) {
      return 'home.html' + $attrs.tplsuffix;
    }

My problems are

  1. I have to literally use the variables $element and $attrs or the .component blows up. I imagine this means that minifying will kill this functionality, and it seems ['$element', '$attrs', function ... ] notation isn't allowed here.
  2. When I call $attrs.tplsuffix I get the non-interpolated version of the string "{{user.lang}}" instead of the value of that variable.

The relevant documentation in rc0 doesn't discuss how to use this nor give a templateUrl function example.

           *      If `template` is a function, then it is {@link auto.$injector#invoke injected} with
           *      the following locals:
           *
           *      - `$element` - Current element
           *      - `$attrs` - Current attributes object for the element
           *
...
           *      If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
           *      the following locals:
           *
           *      - `$element` - Current element
           *      - `$attrs` - Current attributes object for the element

Is this a bug? Or wasn't this function form designed to handle my use case? Or can someone please provide the correct usage if I've just got it wrong? Thanks!

@Narretz
Copy link
Contributor

Narretz commented Dec 13, 2015

The injector issue is fixed by #13485.

The interpolation issue is probably not easily fixable, if at all, as interpolation only happens in the link phase, and the scope is not yet available when the template is requested. So it's just not possible at the moment to evaluate the value before the template is requested.

See here for more discussion: #2895

Generally, I think something like a language parameter to a directive is a bad idea anyway. You'd have to add that to any directive in your application. My suggestion is to provide a requestTransform to the templateRequestProvider that modifies the url to include the language parameter based on a service value.

With dynamic templateUrls you are also losing the advantage of preloading your templates into the templateCache in a build step / when you first request the app.

@Narretz Narretz added this to the Purgatory milestone Dec 13, 2015
@poshest
Copy link
Contributor Author

poshest commented Dec 14, 2015

@Narretz I've been searching for the solution you've just suggested for a while now (see my post from the very issue #2895 you quoted).

Your transformRequest idea is great. I want it! I just have no idea how to make it work. I hit the same dead end as this guy #2063

From the docs

These properties can be a single function that returns the transformed value (function(data, headersGetter, status)

Doesn't say too much about what format the return value should be, and certainly no tips on how to modify just one thing like the url.

My code so far...

.config(function($templateRequestProvider) {
  $templateRequestProvider.httpOptions({
    transformRequest: function (data, headersGetter) {
      var headers = headersGetter();
      return ???;  // return what now?
    }
  });
});

Could you please give me a steer in the right direction? Or did I misinterpret you, and you're in fact suggesting that a new issue be created to add this functionality to Angular?

@Narretz
Copy link
Contributor

Narretz commented Dec 14, 2015

Ah, I was thinking of interceptors, not requestTransform. However, they are not available for templateRequestProvider ...

But, no worries! You can use the httpProvider for that. In this plnkr, I am adding a special property to all templateRequests configs, and then in the interceptor I am adding a prefix: http://plnkr.co/edit/DNvTL5jogbgyb0BqXD5C?p=preview

You could also filter the url by ending, by path etc. Depends where your templates are coming from and if you need prefixing for all of them.

@poshest
Copy link
Contributor Author

poshest commented Dec 14, 2015

This is awesome @Narretz. Thank you very much! Now I've just gotta surmount this problem (my tplsuffix is a collection of variables contained in a couple of services, which don't as yet have providers) and I'm away!

@poshest poshest closed this as completed Dec 14, 2015
@Narretz
Copy link
Contributor

Narretz commented Dec 14, 2015

You can inject into the interceptors! https://code.angularjs.org/1.5.0-rc.0/docs/api/ng/service/$http#interceptors

@poshest
Copy link
Contributor Author

poshest commented Dec 14, 2015

That's magic. Thanks again! :) That's part of Angular that I really haven't understood until now. If only your examples were in the doc...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants