Angular 1.xでは、HTMLタグ_ng-bind-html
_をJavaScript呼び出し$sce.trustAsHTML()
と組み合わせて使用することで、リアルタイムでHTMLを挿入できました。これにより80%の道が開けましたが、_ng-repeat
_またはカスタムディレクティブを使用するHTMLを挿入した場合など、Angularタグが使用されている場合は機能しません。
これを機能させるには、 $ compileを呼び出すカスタムディレクティブ を使用できます。
Angular 2のこのすべてに相当するものは何ですか? _[inner-html]
_を使用してバインドできますが、これは_<b>
_などの非常に単純なHTMLタグでのみ機能します。カスタムangular 2ディレクティブを機能するHTML要素に変換しません。 (Angular 1.xの_$compile
_ステップなしのように。)Angular 2の_$compile
_と同等のものは何ですか?
Angular2では、 DynamicComponentLoader を使用して、ページに「コンパイル済みコンテンツ」を挿入する必要があります。たとえば、次のhtmlをコンパイルする場合:
_<div>
<p>Common HTML tag</p>
<angular2-component>Some angular2 component</angular2-component>
</div>
_
次に、このhtmlをテンプレートとしてコンポーネントを作成し(CompiledComponent
と呼びましょう)、DynamicComponentLoader
を使用してこのコンポーネントをページに挿入します。
_@Component({
selector: 'compiled-component'
})
@View({
directives: [Angular2Component],
template: `
<div>
<p>Common HTML tag</p>
<angular2-component>Angular 2 component</angular2-component>
</div>
`
})
class CompiledComponent {
}
@Component({
selector: 'app'
})
@View({
template: `
<h2>Before container</h2>
<div #container></div>
<h2>After conainer</h2>
`
})
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
_
this plunker をチェックしてください
[〜#〜] upd [〜#〜]loader.loadIntoLocation()
呼び出しの直前にコンポーネントを動的に作成できます。
_// ... annotations
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
// template generation
const generatedTemplate = `<b>${Math.random()}</b>`;
@Component({ selector: 'compiled-component' })
@View({ template: generatedTemplate })
class CompiledComponent {};
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
_
私は個人的にそれが好きではありません、それは私にとって汚いハックのように見えます。しかし、ここに 配管工
[〜#〜] ps [〜#〜]この時点で、angular2が活発に開発されていることに注意してください。したがって、状況はいつでも変更できます。
DynamicComponentLoaderは非推奨です。代わりにComponentResolverを使用できます
このディレクティブを使用して、追加のデータ操作が必要な場合はパイプを追加できます。遅延読み込みも可能です。あなたの場合は必要ありませんが、言及する価値があります。
ディレクティブ(このコードを見つけて、いくつか変更を加えました。好みに合わせて変更することも、そのまま使用することもできます):
import { Component, Directive, ComponentFactory, ComponentMetadata, ComponentResolver, Input, ReflectiveInjector, ViewContainerRef } from '@angular/core';
declare var $:any;
export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);
return resolver.resolveComponent(decoratedCmp);
}
@Directive({
selector: 'dynamic-html-outlet',
})
export class DynamicHTMLOutlet {
@Input() htmlPath: string;
@Input() cssPath: string;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
ngOnChanges() {
if (!this.htmlPath) return;
$('dynamic-html') && $('dynamic-html').remove();
const metadata = new ComponentMetadata({
selector: 'dynamic-html',
templateUrl: this.htmlPath +'.html',
styleUrls: [this.cssPath]
});
createComponentFactory(this.resolver, metadata)
.then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
this.vcRef.createComponent(factory, 0, injector, []);
});
}
}
使用方法の例:
import { Component, OnInit } from '@angular/core';
import { DynamicHTMLOutlet } from './../../directives/dynamic-html-outlet/dynamicHtmlOutlet.directive';
@Component({
selector: 'lib-home',
templateUrl: './app/content/home/home.component.html',
directives: [DynamicHTMLOutlet]
})
export class HomeComponent implements OnInit{
html: string;
css: string;
constructor() {}
ngOnInit(){
this.html = './app/content/home/home.someTemplate.html';
this.css = './app/content/home/home.component.css';
}
}
home.component.html:
<dynamic-html-outlet [htmlPath]="html" [cssPath]="css"></dynamic-html-outlet>
よく読んで、新しいトピックを開くことに近づいたので、他の人を助けるためだけにここで答えることにしました。私が見たように、Angular 2.(現在はBeta9)の最新バージョンでいくつかの変更があります。
私が持っていた同じ欲求不満を避けるために、コードを共有しようとします...
まず、index.html
いつものように、次のようなものが必要です。
<html>
****
<body>
<my-app>Loading...</my-app>
</body>
</html>
AppComponent(innerHTMLを使用)
このプロパティを使用すると、基本的なHTMLをレンダリングできますが、スコープを介して$ compileとしてAngular 1.xのような何かを行うことはできません。
import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div [innerHTML]="htmlExample"></div>
`,
})
export class AppComponent {
public title = 'Angular 2 app';
public htmlExample = ' <div>' +
'<span [textContent]="\'Hello my Property bound: \'+title"></span>' +
'<span>Hello my Interpolated: {{title}}</span>' +
'</div>'
}
これにより、以下がレンダリングされます。
こんにちは私の補間:Angular 2アプリ!
こんにちは、プロパティのバインド:Angular 2 app!
こんにちは私の補間:{{title}}
DynamicComponentLoaderを使用したAppComponent
here で文書化されているドキュメントには小さなバグがあります。そのことを念頭に置いておくと、私のコードは次のようになります。
import {DynamicComponentLoader, Injector, Component, ElementRef, OnInit} from "angular2/core";
@Component({
selector: 'child-component',
template: `
<div>
<h2 [textContent]="'Hello my Property bound: '+title"></h2>
<h2>Hello my Interpolated: {{title}}</h2>
</div>
`
})
class ChildComponent {
title = 'ChildComponent title';
}
@Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div #child></div>
<h1>End of parent: {{endTitle}}</h1>
`,
})
export class AppComponent implements OnInit{
public title = 'Angular 2 app';
public endTitle= 'Bye bye!';
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
// dynamicComponentLoader.loadIntoLocation(ChildComponent, elementRef, 'child');
}
ngOnInit():any {
this.dynamicComponentLoader.loadIntoLocation(ChildComponent, this.elementRef, 'child');
}
}
これにより、以下がレンダリングされます。
こんにちは私の補間:Angular 2アプリ!
こんにちは、プロパティのバインド:Angular 2 app!
Helloバインドされたプロパティ:ChildComponentタイトル
こんにちは、Interpolated:ChildComponentタイトル
親の終わり:さようなら!
あなたがしなければならないことは、HTMLをコンパイルしたい要素を[innerHTML] = "yourcomponentscopevar"で設定することだけだと思います
このモジュールをご覧ください https://www.npmjs.com/package/ngx-dynamic-template
長い研究の後、このことだけが私を助けました。残りのソリューションは時代遅れのようです。
Angularはhtmlを動的にロードするDynamicComponentLoader
クラスを提供しました。 DynamicComponentLoader
には、コンポーネントを挿入するためのメソッドがあります。 loadIntoLocation
はコンポーネントを挿入するためのそれらの1つです。
paper.component.ts
import {Component,DynamicComponentLoader,ElementRef,Inject,OnInit} from 'angular2/core';
import { BulletinComponent } from './bulletin.component';
@Component({
selector: 'paper',
templateUrl: 'app/views/paper.html'
}
})
export class PaperComponent {
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
}
ngOnInit(){
this.dynamicComponentLoader.loadIntoLocation(BulletinComponent, this.elementRef,'child');
}
}
bulletin.component.ts
import {Component} from 'angular2/core';
@Component({
selector: 'bulletin',
templateUrl: 'app/views/bulletin.html'
}
})
export class BulletinComponent {}
paper.html
<div>
<div #child></div>
</div>
あなたが世話をする必要があるいくつかのこと:
loadIntoLocation
を呼び出さないでください。コンポーネントコンストラクターが呼び出されたとき、コンポーネントビューはまだ作成されていません。エラーが発生します-AppComponent!のインスタンス化中にエラーが発生しました。要素[object Object]にはコンポーネントディレクティブがありません
変数の子が見つかりませんでした