2017-09-22 17 views
-1

私はテンプレートを使って何をしようとしているのか、あるいは動作しているかどうかを調べるために、ここでさまざまなブログ投稿とトピックを読んできました。角4とダイナミックテンプレート

私たちは、単にアイコンとサイズは、それを使用してテンプレートで必要とされる部品や指定を使用して設定された構造では非常に単純ですアイコンコンポーネントを持っている:

import {Component, Input} from '@angular/core'; 

@Component({ 
    selector: 'comp-icon', 
    template: ` 
     <span class="{{ class }}" *ngIf="icon === 'error'" > 
      <svg [attr.height]="size" viewBox="0 0 48 48" [attr.width]="size" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg> 
     </span> 
     <span class="{{ class }}" *ngIf="icon === 'success'" > 
      <svg [attr.height]="size" viewBox="0 0 48 48" [attr.width]="size" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg> 
     </span> 
    ` 
}) 
export class IconComponent { 
    @Input() icon: string; 
    @Input() size: number; 
    @Input() class: string; 

    constructor() { 
    } 
} 

問題があることですこれ以上の行が繰り返されており、このコンポーネントを実装しているライブラリを使用するさまざまなアプリケーションからカスタムSVGイメージをリストに追加する機能を追加しようとしています。

import {Component, Input, OnInit, ViewChild} from '@angular/core'; 
import {Icons} from './icons'; 

@Component({ 
    selector: 'comp-icon', 
    template: ` 
     <span class="{{ class }}"> 
      <ng-container [ngTemplateOutlet]="iconContent"></ng-container> 
     </span> 
    ` 
}) 
export class IconComponent implements OnInit { 
    @Input() icon: string; 
    @Input() size: number; 
    @Input() class: string; 

    @ViewChild('iconContent') iconContent: any; 

    constructor() { 
    } 

    ngOnInit() { 
     this.iconContent = (Icons.find(icon => icon.name === this.icon) || { name: '', content: '' }).content; 
    } 
} 

とそれに対応するicons.tsは、次のようになります:

export interface IIcon { 
    name: string; 
    content: string; 
} 

export const Icons: IIcon[] = [ 
    { 
     name: 'error', 
     content: `<svg [attr.height]="{SIZE}" [attr.width]="{SIZE}" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"> 
     </svg>` 
    }, 
    { 
     name: 'success', 
     content: `<svg [attr.height]="{SIZE}" [attr.width]="{SIZE}" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"> 
     </svg>` 
    }, 
]; 

はそれがに可能なすべてのです今のところ、これは、私は基本的に我々が達成しようとしているものを示している管理しているものですこのようにしてコンポーネントのセクションの内容を動的に指定します。この場合、svg?私はディレクティブがこれを達成できるかについていくつか読んだことがありますが、実際に何も出ていないか、実際にはどう考えていません。

+0

コンポーネントや角度属性などのバインディングを使用したい場合は、実行時にコンポーネントをコンパイルする必要があります。例えばhttps://stackoverflow.com/questions/38888008/how-can-i-use-create-dynamic-template-to-compile-dynamic-component-with-angularを参照してください –

+0

私は必ずしもそうする必要はありません'innerHTML'はsvgsが好きではないので、私は選択肢の多くを持っているように見えません。リンクをありがとう、私はそれを見てみましょう。 S.誰がそれをしたのかについては、下降票が何であったのかはっきりしない。 – DavidIQ

+0

svgはinnerHTMLでは使用できますが、バインディングは使用できません。安全なhttps://stackoverflow.com/questions/31548311/angular-2-html-binding/41089093#41089093としてマークする必要があります。 TypeScriptの文字列補間は**の前に**バインディングの代わりにinnerHTMLに渡すことができます。 –

答えて

0

プロパティのバインドにinnerHTMLを使用できます。コンポーネントを作成する場合は、チェックアウトする必要があります。GünterZöchbauerのsuggetion。

<div [innerHTML]="iconContent"> 
</div> 

別の可能な解決策は、

export const Icons: IIcon[] = [ 
    { 
     name: 'error', 
     width: '50px', 
     heigth: '50px', 
     viewBox: '0 0 48 48', 
     xmlns: "http://www.w3.org/2000/svg" 
    } 
]; 

することができ、その後、あなたのコンポーネントのhtml

<svg [attr.width]="iconContent.width" [attr.heigth]="iconContent.height" [attr.viewBox]="iconContent.viewBox" [attr.xmlns]="xmlns"></svg> 
+0

ええ、私はこれを試しましたが、Angularは私に素晴らしい「WARNING:衛生的なHTMLはいくつかのコンテンツを取り除いた」というメッセージを出しました。これは明らかにSVG全体を取り除くことを意味します。 – DavidIQ

+0

@DavidlQあなたは何をしているのかをあなたに知らせる必要がありますsvgコンテンツチェックのための出力のサニタイズを無効にするhttps://angular.io/guide/security –

0

でこれを行うための適切な方法は、私が最初にしようとしていたとして、実際にngComponentOutletを使用することでした。 this postに基づいて、私は次のように、ほとんど逐語的に、それを実装しました:

import { Compiler, Component, ElementRef, Input, NgModule, NgModuleFactory, OnInit, ViewChild } from '@angular/core'; 
import { IconsProvider } from './icons.provider'; 

@Component({ 
    selector: 'comp-icon', 
    template: ` 
     <ng-container *ngComponentOutlet="dynamicIconComponent; 
         ngModuleFactory: dynamicIconModule;"></ng-container> 
    ` 
}) 
export class IconComponent implements OnInit { 
    @Input() icon: string; 
    @Input() size: number; 
    @Input() class: string; 

    public dynamicIconComponent: any; 
    public dynamicIconModule: NgModuleFactory<any>; 

    constructor (private _iconsProvider: IconsProvider, private _compiler: Compiler) { 
    } 

    ngOnInit() { 
     const selectedIcon: string = this._iconsProvider.getIcon(this.icon); 

     if (selectedIcon != null) { 
      this.dynamicIconComponent = this.createNewIconComponent(selectedIcon, this.class, this.size); 
      this.dynamicIconModule = this._compiler.compileModuleSync(this.createIconComponentModule(this.dynamicIconComponent)); 
     } 
    } 

    private createIconComponentModule(iconComponentType: any) { 
     @NgModule({ 
      imports: [], 
      declarations: [ 
       iconComponentType 
      ], 
      entryComponents: [iconComponentType] 
     }) 
     class RuntimeIconComponentModule {} 

     return RuntimeIconComponentModule; 
    } 

    private createNewIconComponent(iconContents: string, iconClass: string, iconSize: number) { 
     @Component({ 
      selector: 'dynamic-icon-component', 
      template: `<span class="{{ iconClass }}">${iconContents}</span>` 
     }) 
     class DynamicIconComponent implements OnInit { 
      private iconContents: string; 
      private iconClass: string; 
      private size: number; 

      ngOnInit() { 
       this.iconContents = iconContents; 
       this.iconClass = iconClass; 
       this.size = iconSize; 
      } 
     } 

     return DynamicIconComponent; 
    } 
} 

コメントや提案が最終的な答えに私の方法を見つけることに非常に有用でした。ありがとうございました。

関連する問題