Angularjs (e.g. angular 1) had this convenient behaviour of searching for a element which had the id of the given templ
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 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