Angularjs (e.g. angular 1) had this convenient behaviour of searching for a <script type="text/ng-template"> element which had the id of the given template url before requesting it to the server.
Ex: The code below is not triggering any additional http request
<script type="text/ng-template" id="mytemplate.html">
This is a body for my template
</script>
<script>
//...
app.directive('myComponent', function() {
return {
templateUrl: 'mytemplate.html' // does NOT trigger a http get
};
});
</script>
This does not seems to work using Angular 2.
@View({
templateUrl: 'mytemplate.html', // will be fetched from server !
})
class MyComponent{}
Is there another way of achieving it ? Am I missing something ?
ps: i do not wish to embbed all my html in my ts files...
In Angular, a template is a chunk of HTML. Use special syntax within a template to build on many of Angular's features.
What is ng-template in Angular? ng-template is an Angular element that is used for rendering HTML in a template. However, it is not rendered directly on DOM. If you include an ng-template tag to a template, the tag and the content inside it will be replaced by comment upon render.
One of the main uses for <ng-template> is to hold template content that will be used by Structural directives. Those directives can add and remove copies of the template content based on their own logic.
The let keyword in Angular declares a template input variable that is referenced within the template. In Angular, the micro syntax is used to configure a directive in a compact and friendly string.
If anyone is interested, i found a simple workaround (a cleaner solution would be better, though)
function template(url, viewdef) {
var elt = document.getElementById(url);
if (elt && elt.getAttribute('type') == 'text/ng-template') {
viewdef.template = elt.innerHTML;
} else
viewdef.templateUrl = url;
return viewdef;
}
@View(template('mytemplate.html', {
directives: [NgIf /*required directives*/]
}))
class MyComponent{}
But it assumes that the <script> is already present when this script is loaded.
[EDIT] Better workaround
I just came up with the simple idea to just override the @View
decorator factory.
1) Create a viewoverride.ts
file
import * as ng from 'angular2/core'
let oldNgView = ng.View;
function ViewOverride(viewDef) {
if (typeof viewDef.templateUrl == "string") {
let elt = document.getElementById(viewDef.templateUrl);
if (elt && elt.getAttribute('type') == 'text/ng-template') {
viewDef.template = elt.innerHTML;
delete viewDef.templateUrl;
}
}
return oldNgView(viewDef);
}
ng.View = <ng.ViewFactory>ViewOverride;
nb: It's very important to put it in a separate and independant file, to force it to be executed before other imports
2) And put this as the first line of your bootstrap file:
import './viewoverride'
3) That's it. The @View notation is now overriden
@View({templateUrl:'mytemplate.template'}) class MyClass{}
will now seek for a script element which id is mytemplate.template
I think a cleaner way for this would be if you provide your custom ViewResolver
, inspired by the angular beta 17's source code, something in the lines of:
import { Type, ViewMetadata, Reflector, Injectable, ComponentMetadata } from 'angular2/core';
import { ViewResolver } from 'angular2/compiler';
const SCRIPT_TYPE_NAME = 'text/ng2-template';
@Injectable()
export class CustomViewResolver extends ViewResolver
{
constructor(private _r: Reflector){ super() }
resolve(component: Type): ViewMetadata
{
let annotations = this._r.annotations(component);
annotations.forEach( cm =>
{
if(cm instanceof ComponentMetadata && cm.templateUrl && typeof cm.templateUrl == 'string' )
{
let elemTpl = (<any>document).getElementById(cm.templateUrl);
if( elemTpl && elemTpl.getAttribute('type') == SCRIPT_TYPE_NAME )
{
cm.template = elemTpl.innerHTML;
elemTpl.remove();
cm.templateUrl = undefined
}
else
throw new Error(`template "${cm.templateUrl}" not found among html scripts`)
}
})
return super.resolve(component)
}
}
Plunker Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With