web-dev-qa-db-fra.com

Angular2, évalue le modèle à partir d'une chaîne dans un composant

Il est possible d'évaluer le modèle à partir d'une chaîne dans une variable?. J'ai besoin de placer la chaîne dans le composant au lieu de l'expression, Par exemple. 

template: "<div>{{ template_string }}</div>"

template_string contient: <b>{{ name }}</b> 

et tout devrait être évalué à <div><b>My Name</b></div> 

mais je vois <div>{{ template_string }}</div>

J'ai besoin de quelque chose comme {{ template_string | eval }} ou autre chose pour évaluer le contenu de la variable sur le contexte actuel.

C'est possible? J'ai besoin de quelque chose pour utiliser cette approche car template_string peut être modifié lorsque le composant est utilisé. 

Edit1: 

Version angulaire: 4.0.3

Par exemple.

@Component({
  selector: 'product-item',
  template: `
    <div class="product">{{ template }}</div>`,
})
export class ProductItemComponent {
  @Input() name: string;
  @Input() price: number = 0;
  @Input() template: string = `{{ name }} <b>{{ price | currency }}</b>`;
}

Usage:

<product-item [name]="product.name" [price]="product.price"></product-item>

Attendu: Nom du produit USD3.00

Sortie: {{ name }} <b>{{ price | currency }}</b>

6
rafrsr

Vous pouvez créer votre propre directive qui le fera:

compile.directive.ts

@Directive({
  selector: '[compile]'
})
export class CompileDirective implements OnChanges {
  @Input() compile: string;
  @Input() compileContext: any;

  compRef: ComponentRef<any>;

  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {}

  ngOnChanges() {
    if(!this.compile) {
      if(this.compRef) {
        this.updateProperties();
        return;
      }
      throw Error('You forgot to provide template');
    }

    this.vcRef.clear();
    this.compRef = null;

    const component = this.createDynamicComponent(this.compile);
    const module = this.createDynamicModule(component);
    this.compiler.compileModuleAndAllComponentsAsync(module)
      .then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
        let compFactory = moduleWithFactories.componentFactories.find(x => x.componentType === component);

        this.compRef = this.vcRef.createComponent(compFactory);
        this.updateProperties();
      })
      .catch(error => {
        console.log(error);
      });
  }

  updateProperties() {
    for(var prop in this.compileContext) {
      this.compRef.instance[prop] = this.compileContext[prop];
    }
  }

  private createDynamicComponent (template:string) {
    @Component({
      selector: 'custom-dynamic-component',
      template: template,
    })
    class CustomDynamicComponent {}
    return CustomDynamicComponent;
  }

  private createDynamicModule (component: Type<any>) {
    @NgModule({
      // You might need other modules, providers, etc...
      // Note that whatever components you want to be able
      // to render dynamically must be known to this module
      imports: [CommonModule],
      declarations: [component]
    })
    class DynamicModule {}
    return DynamicModule;
  }
}

Usage:

@Component({
  selector: 'product-item',
  template: `
    <div class="product">
      <ng-container *compile="template; context: this"></ng-container>
    </div>
  `,
})
export class ProductItemComponent {
  @Input() name: string;
  @Input() price: number = 0;
  @Input() template: string = `{{ name }} <b>{{ price | currency }}</b>`;
}

Exemple Plunker

Voir également

15
yurzui

je ne sais pas comment vous construisez la chaîne de template

import { ..., OnInit } from '@angular/core';

@Component({
    selector: 'product-item',
    template: `
    <div class="product" [innerHtml]='template_string'>
    </div>`,
    })
export class ProductItemComponent implements OnInit {
    @Input() name: string;
    @Input() price: number = 0;
    @Input() pre: string;
    @Input() mid: string;
    @Input() post: string;
    template_string;
    ngOnInit() {
        // this is probably what you want
        this.template_string = `${this.pre}${this.name}${this.mid}${this.price}${this.post}`
    }
}

<product-item [name]="name" [price]="price" pre="<em>" mid="</em><b>" post="</b>"></product-item>

la chaîne peut être construite de l'extérieur du composant, recommanderait néanmoins quelque chose comme ngIf pour contrôler les modèles dynamiques.

0
tesgo

Dans Angular, les doubles accolades {{}} sont utilisées pour évaluer une expression dans le modèle d'un composant. et ne pas travailler sur des chaînes aléatoires ou des éléments DOM ajoutés dynamiquement. Donc, une façon de faire est d'utiliser une interpolation de chaîne TypeScript en utilisant ${}. vérifier le reste du code pour comprendre

@Component({
  selector: 'product-item',
  template: `
    <div class="product" [innerHTML]="template"></div>`,
})
export class ProductItemComponent {
  @Input() name: string;
  @Input() price: number = 0;
  @Input() template: string = `${ this.name } <b>${ this.price }}</b>`;
}
0
Khurram