Шаблон как <script type = "text/ng-template" > эквивалент с angular 2
Angularjs (например, angular 1) имел это удобное поведение для поиска элемента < script type = "text/ng-template" > , который имел идентификатор данного шаблон URL, прежде чем запрашивать его на сервере.
Пример: приведенный ниже код не запускает дополнительный HTTP-запрос
<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>
Это не работает, используя angular 2.
@View({
templateUrl: 'mytemplate.html', // will be fetched from server !
})
class MyComponent{}
Есть ли другой способ его достижения? Я что-то пропустил?
ps: я не хочу вставлять все мои html в мои ts файлы...
Ответы
Ответ 1
Если кому-то интересно, я нашел простой способ обхода (более чистое решение было бы лучше)
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{}
Но он предполагает, что <script> уже присутствует, когда загружается этот script.
[EDIT] Лучшее обходное решение
Я просто придумал простую идею, чтобы просто переопределить декоратор @View
factory.
1) Создайте файл viewoverride.ts
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: Очень важно разместить его в отдельном и независимом файле, чтобы заставить его выполнить перед другими импортными
2) И поставьте это как строку first вашего файла начальной загрузки:
import './viewoverride'
3) Это. Обозначение @View теперь переопределено
@View({templateUrl:'mytemplate.template'}) class MyClass{}
теперь будет искать элемент script, который id mytemplate.template
Ответ 2
Я думаю, что более чистым способом для этого было бы, если бы вы предоставили свой собственный ViewResolver
, вдохновленный исходным кодом angular beta 17, что-то в строках:
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)
}
}
Ссылка на плейер