Angular 2 equivalente de ng-bind-html, $ sce.trustAsHTML () e $ compile?

No Angular 1.x, poderíamos inserir HTML em tempo real usando a tag HTML ng-bind-html , combinada com a chamada JavaScript $sce.trustAsHTML() . Isso nos levou a 80% do caminho até lá, mas não funcionou quando foram usadas tags Angular, como se você tivesse inserido HTML que usasse diretivas ng-repeat ou customizadas.

Para fazer isso funcionar, poderíamos usar uma diretiva personalizada chamada $ compile .

Qual é o equivalente para tudo isso em Angular 2? Podemos nos ligar usando [inner-html] mas isso só funciona para tags HTML muito simples, como . Não transforma diretivas angulares personalizadas em elementos HTML funcionais. (Muito parecido com o Angular 1.x sem o passo $compile .) Qual é o equivalente a $compile para o Angular 2?

Em Angular2 você deve usar DynamicComponentLoader para inserir algum “conteúdo compilado” na página. Por exemplo, se você quiser compilar o próximo html:

 

Common HTML tag

Some angular2 component

então você precisa criar um componente com este html como um modelo (vamos chamá-lo CompiledComponent ) e usar DynamicComponentLoader para inserir este componente na página.

 @Component({ selector: 'compiled-component' }) @View({ directives: [Angular2Component], template: ` 

Common HTML tag

Angular 2 component
` }) class CompiledComponent { } @Component({ selector: 'app' }) @View({ template: `

Before container

After conainer

` }) class App { constructor(loader: DynamicComponentLoader, elementRef: ElementRef) { loader.loadIntoLocation(CompiledComponent, elementRef, 'container'); } }

Confira esta plunker

UPD Você pode criar um componente dinamicamente antes da chamada do loader.loadIntoLocation() :

 // ... annotations class App { constructor(loader: DynamicComponentLoader, elementRef: ElementRef) { // template generation const generatedTemplate = `${Math.random()}`; @Component({ selector: 'compiled-component' }) @View({ template: generatedTemplate }) class CompiledComponent {}; loader.loadIntoLocation(CompiledComponent, elementRef, 'container'); } } 

Eu pessoalmente não gosto disso, parece um truque sujo para mim. Mas aqui é o plunker

PS Cuidado com o fato de que neste momento o angular2 está em desenvolvimento ativo. Então, a situação pode ser alterada a qualquer momento.

DynamicComponentLoader está obsoleto, você pode usar o ComponentResolver

Você poderia usar essa diretiva, adicionar pipes se precisar de manipulação de dados adicionais. Também permite carregamento lento, você não precisa no seu caso, mas vale a pena mencionar.

Directiva (encontrei este código e fiz algumas alterações, pode fazê-lo também para o adaptar ao seu gosto ou usá-lo como está):

 import { Component, Directive, ComponentFactory, ComponentMetadata, ComponentResolver, Input, ReflectiveInjector, ViewContainerRef } from '@angular/core'; declare var $:any; export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise> { 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, []); }); } } 

Exemplo de como usar:

 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:

  

Depois de ler muito e estar perto de abrir um novo tópico resolvi responder aqui só para tentar ajudar os outros. Como eu vi, existem várias mudanças com a versão mais recente do Angular 2. (Atualmente Beta9)

Vou tentar compartilhar meu código para evitar a mesma frustração que tive …

Primeiro, no nosso index.html

Como de costume, devemos ter algo assim:

  ****  Loading...   

AppComponent (usando innerHTML)

Com essa propriedade, você poderá renderizar o HTML básico, mas não poderá fazer algo semelhante ao Angular 1.x como $ compile por meio de um escopo:

 import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: ` 

Hello my Interpolated: {{title}}!

`, }) export class AppComponent { public title = 'Angular 2 app'; public htmlExample = '
' + '' + 'Hello my Interpolated: {{title}}' + '
' }

Isso renderizará o seguinte:

Olá meu Interpolado: Angular 2 app!

Olá meu Imóvel vinculado: Angular 2 app!

Olá meu Interpolado: {{title}}

AppComponent usando DynamicComponentLoader

Há um pequeno bug com os documentos, documentados aqui . Então, se tivermos em mente que, meu código deve ficar assim:

 import {DynamicComponentLoader, Injector, Component, ElementRef, OnInit} from "angular2/core"; @Component({ selector: 'child-component', template: ` 

Hello my Interpolated: {{title}}

` }) class ChildComponent { title = 'ChildComponent title'; } @Component({ selector: 'my-app', template: `

Hello my Interpolated: {{title}}!

End of parent: {{endTitle}}

`, }) 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'); } }

Isso renderizará o seguinte:

Olá meu Interpolado: Angular 2 app!

Olá meu Imóvel vinculado: Angular 2 app!

Olá minha propriedade ligada: título ChildComponent

Olá meu título Interpolated: ChildComponent

Fim do pai: Tchau, tchau!

Eu acho que tudo que você tem a fazer é definir o elemento que você deseja ter compilado html com o [innerHTML] = “yourcomponentscopevar”

Angular forneceu a class DynamicComponentLoader para carregar o html dinamicamente. DynamicComponentLoader tem methods para inserir componentes. loadIntoLocation é um deles para inserir o componente.

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

 

Poucas coisas que você precisa cuidar:

  • Não chame loadIntoLocation dentro do construtor da class. A visualização de componentes ainda não é criada quando o construtor do componente é chamado. Você vai ter erro –

Erro durante a instanciação do AppComponent !. Não há diretiva de componente no elemento [object Object]

  • Coloque anchorName #child em html caso contrário, você receberá um erro.

Não foi possível encontrar filho variável

Dê uma olhada neste módulo https://www.npmjs.com/package/ngx-dynamic-template

Depois de uma longa pesquisa, só isso me ajudou. O resto das soluções parece estar desatualizado.