help español documentacion docs angular2 javascript angular

javascript - español - https angular io docs



URL de plantillas dinámicas en Angular 2 (9)

¡Espero, el ejemplo de github para ti te ayudará! Hay ejemplos para compilar html dinámico. Por lo tanto, puede cargar HTML mediante cualquiera de sus Servicios y luego compilarlo.

He estado jugando con Angular 2 durante los últimos días y me pregunté si sería posible proporcionar una templateUrl dinámica al decorador @View .

Intenté pasarle una función y devolverle una cadena, pero toda la función se convierte en una cadena.

Realmente no he usado Angular 1.x antes, así que no sé si solo voy a hacerlo de manera incorrecta, pero ¿es esto posible o hay una mejor manera de crear vistas dinámicas?

Por ejemplo, podría querer mostrar un formulario si el usuario no ha iniciado sesión, pero mostrar un mensaje de texto si ha iniciado sesión.

Algo como esto no funciona:

@Component({ selector: ''my-component'' }) @View({ // This doesn''t work templateUrl: function() { return this.isLoggedIn ? ''logged-in.html'' : ''logged-out.html''; } }) class MyComponent { constructor() { this.loggedIn = false; } }

Cualquier ayuda sería apreciada.


1- instala esta biblioteca

npm i -D html-loader

================================================== ==========

2- En webpack.config use html-loader para archivos html

{ test: //.html$/, loaders: [''html-loader''] }

================================================== ==========

3- Si usa iónico, puede copiar webpack.config.js desde la ruta "node_modules/@ionic/app-scripts/config/webpack.config.js" y luego agregarle el cargador html

================================================== ===========

4-Si usa ionic In package.json agregue estas líneas

"config": { "ionic_bundler": "webpack", "ionic_webpack": "webpack.config.ionic.js" },

================================================== ===========

5-Entonces puedes usarlo de la siguiente manera

@Component({ selector: ''page-login'', // templateUrl:"./login.html" template: function(){ if(globalVariables.test==2) { return require("./login2.html") } else { return require("./login.html") } }(), })

======================================

6-Si hay un error no resuelto con la función require, puede ponerlo en el archivo declarations.d.ts como se muestra a continuación:

declarar var requiere: cualquiera;


Actualización de la respuesta de @Eyal Vardi ( ViewResolver está en desuso):

import { Directive, Type, Component } from ''@angular/core''; import { DirectiveResolver } from ''@angular/compiler''; class myViewUrlResolver extends DirectiveResolver { resolve(type: Type<any>, throwIfNotFound?: boolean): Directive { let view = <any>super.resolve(type, throwIfNotFound); if (typeof view["templateUrl"] !== "undefined") { console.log("Yay!"); let originalUrl = (<Component>view).templateUrl; (<Component> view).templateUrl = environment.nativeScriptAppPrePathPrefix + originalUrl.replace(".html", ".tns.html"); } if (typeof view["styleUrls"] !== "undefined") { console.log("Yay2!"); let originalUrls = (<Component>view).styleUrls; originalUrls.forEach((originalUrl, at) => (<Component>view).styleUrls[at] = environment.nativeScriptAppPrePathPrefix + originalUrl.replace(".html", ".tns.css")); } return view; } } platformNativeScriptDynamic().bootstrapModule(AppModule,{ providers: [ { provide: DirectiveResolver, useClass: myViewUrlResolver } ] });


Aunque quizás no sea la solución más elegante, utilicé DynamicComponentLoader y ElementRef para asignar dinámicamente el valor de la plantilla a un componente. De hecho, estaba buscando una solución donde pudiera agregar múltiples componentes personalizados en un marcador de posición.

Intenté la inyección de servicio en la función como se describe en shmck, esto no funciona ya que los servicios aún no están disponibles cuando se llama a la función de plantilla. De hecho, this refiere al objeto Window.

Las URL de referencia para la solución que utilicé se encuentran en: crear anchorName / componentes dinámicos con ComponentResolver y ngFor en Angular2

También me refiero de esta manera a Plnkr1 y Plnkr2 .

El sitio Dartdocs proporciona buena documentación sobre la clase Angular 2 DynamicComponentLoader, también aplicable a TypeScript.

En breve:

Un componente simple como la plantilla que se utilizará

@Component({ selector: ''dt2-simple-block'', properties: ["idx"], template: `<h1>Simple block for {{ idx }} </h1>`, directives: [] }) class dt2SimpleBlock { constructor() { } }

Constructor del componente que contiene todos los componentes que se agregarán (mi aplicación requiere que se incluyan varios elementos secundarios:

constructor(loader: DynamicComponentLoader, elementRef: ElementRef) { //iterate for (var i = 0; i < toSomething; i++) { // build the template var blockdirective = ''dt2-simple-block'' var template = ''<'' + blockdirective + '' idx="'' + this.userBlocks.userHomePanelBlocks[i] + ''"></'' + blockdirective + ''>''; console.log(template); // debugging purpose var directives = [dt2SimpleBlock]; loader.loadNextToLocation(toComponent(template, directives), elementRef); }

Y la función auxiliar se debe colocar en algún lugar como util

function toComponent(template, directives = []) { @Component({ selector: ''fake-component'' }) @View({ template, directives }) class FakeComponent { } return FakeComponent; }


Compile su aplicación con un "ng serve --aot".

export let DEFAULT_PREFIX :string= ''./app.component''; //or localStorage.getItem(''theme'') export function getMySuperTemplate(template: string) { return DEFAULT_PREFIX + template + ''.html''; } @Component({ selector: ''app-root'', templateUrl: getMySuperTemplate(''2''), styleUrls:[''./app.component.css''] })


Mi solución:

Clase Angular 2.0 ViewResolver

class myViewResolver extends ViewResolver{ resolve(component: Type): ViewMetadata { var view = super.resolve(component); // TODO: Write logic here:-) view.templateUrl = ''app/app.html''; return view; } } bootstrap(App,[ provide(ViewResolver , {useClass:myViewResolver}) ]);


Mi solución: (La belleza de esto es la carga diferida para archivos html y css).

Esto es home.componenet.ts

import { Component } from ''@angular/core''; import { DynamicHTMLOutlet } from ''./../../directives/dynamic-html-outlet/dynamicHtmlOutlet.directive''; import { TranslateService, LangChangeEvent } from ''ng2-translate/ng2-translate''; @Component({ selector: ''lib-home'', templateUrl: ''./app/content/home/home.component.html'', directives: [DynamicHTMLOutlet] }) export class HomeComponent { html_template = `./app/content/home/home_`; html: string; css: string; constructor(translate: TranslateService) { this.html = this.html_template + translate.currentLang; this.css = ''./app/content/home/home.component.css''; translate.onLangChange.subscribe((event: LangChangeEvent) => { this.html = this.html_template + translate.currentLang; this.css = ''./app/content/home/home.component.css''; }); } }

La directiva que usé e hice algunos cambios: está en home.componenet.html

<dynamic-html-outlet [htmlPath]="html" [cssPath]="css"></dynamic-html-outlet>

Esta es la directiva para componentes dinámicos:

import { Component, Directive, ComponentFactory, ComponentMetadata, ComponentResolver, Input, ReflectiveInjector, ViewContainerRef, } from ''@angular/core''; import { TranslatePipe } from ''ng2-translate/ng2-translate''; 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], pipes: [TranslatePipe] }); createComponentFactory(this.resolver, metadata) .then(factory => { const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); this.vcRef.createComponent(factory, 0, injector, []); }); } }


No es exactamente lo que pediste, pero vale la pena mencionarlo:

Otra solución simple, que funciona para la mayoría de los casos de uso, es poner la lógica en la plantilla misma, de esta manera:

@Component({ selector: ''my-component'' }) @View({ // Note1: Here, I use template instead of templateUrl. // Note2: I use ES6 string interpolation + require() to embed/load the other templates, but you can do it however you like. template: ` <div [ngSwitch]="loggedIn"> <template [ngSwitchCase]="true"> ${require(''./logged-in.html'')} </template> <template ngSwitchDefault> ${require(''./logged-out.html'')} </template> </div>` }) class MyComponent { constructor() { this.loggedIn = false; } }

La desventaja de esta solución es que su archivo js servido termina conteniendo ambas plantillas, por lo que esto podría ser un problema para las plantillas grandes (pero solo se representa una plantilla y la sobrecarga del tamaño js es aceptable en muchos casos).


Parece que esta forma de crear plantillas dinámicas no estará disponible para Angular 2 debido a cuestiones de seguridad. Desafortunadamente, viniendo de Angular 1, mi aplicación anterior fue impulsada dinámicamente de esta manera.

Para Angular 2: esta podría ser una forma diferente de hacer lo mismo (ejemplo de enlace a continuación). Al actualizar los archivos html de la plantilla para que sean componentes en la aplicación, luego los inyecta (en el lugar donde estaba tratando de crear templateUrl con una cadena, etc.) ver el parámetro de la plantilla del componente como elementos (usando DynamicComponentLoader)

https://angular.io/docs/js/latest/api/core/DynamicComponentLoader-class.html