2017-05-19 11 views
1
を渡す

私はテーブルを作成するための簡単な部品作り:上記のコンポーネント角度、どのように解析文字列からテンプレートと現在のコンテキスト変数に

@Component({ 
    selector: 'product-admin', 
    template: ` 
    <h1>Products</h1> 
    <admin-table [columns]="columns" [records]="products"></admin-table> 
    `, 
    providers: [ProductService], 
}) 
export class ProductAdminComponent implements OnInit { 

    products: Product[]; 

    columns: AdminTableColumn[] = [ 
    { 
     field: 'id', 
     label: 'SKU', 
    }, 
    { 
     field: 'name', 
     label: 'Name', 
     template: '<strong>{{record.name}}</strong>', 
    } 
    ]; 
} 
を使用した製品のテーブルを作成するために

@Component({ 
    selector: 'admin-table', 
    template: ` 
    <table class='table table-bordered'> 
     <thead> 
     <th *ngFor='let column of columns'> 
     {{ column.label }} 
     </th> 
     </thead> 
     <tbody> 
     <tr *ngFor="let record of records"> 
     <td *ngFor='let column of columns' [innerHTML]="fieldContent(column, record) | safeHtml"> 
     </td> 
     </tr> 
     </tbody> 
    </table> 
    `, 
}) 
export class AdminTableComponent { 

    @Input() columns: AdminTableColumn[]; 

    @Input() records: {}[]; 

    fieldContent(column: AdminTableColumn, record: {}) { 
    if (column.template) { 
     //TODO: parse the template and pass current record as argument 
     return column.template; 
    } 

    return record[column.field]; 
    } 
} 

およびその他のコンポーネントを

AdminTableColumnにはtemplateという追加のオプションがあり、テンプレートを使用してセルの値を設定することができます。しかし、実際の製品名の代わりに{{record.name}}という値を表示しようとすると、これを行うことはできません。

templateオプションに入力された値を解析して、豊富な表を作成するために、{{record.name}}または<some-component [title]="record.name"></some-component>のような角の宣言を使用できるようにする必要があります。言い換えれば

は、私は角度があなたの文字列補間が動作しませんので、innerHTMLプロパティを介して注入HTMLをサニタイズかなり確信しているrender(template, { record: record })

+0

あなたはバインディング '[innerHTMLプロパティ]'プロパティを使用することができます。価値があるショットhttp://stackoverflow.com/questions/34936027/angular-2-how-do-you-render-html-from-a-json-response-without-displaying-the-ta –

+0

currenly私は使用しています'[innerHTML] '、' [innerHTML] = "fieldContent(column、record)| safeHtml"という行を参照してください。コンテンツは(raw)としてレンダリングされますが、 'record'のような変数を渡す必要があります。 – rafrsr

+0

おそらく、 'ChangeDetectorRef'を注入してから' detectChanges() 'を呼び出してみてください。あるいは、他のアプローチは 'NgZone'を注入してから' run() 'を実行しているようです。 –

答えて

2

あなたは、この目的のために特別な指示を構築することができます:

@Component({ 
    selector: 'admin-table', 
    template: ` 
    <table class='table table-bordered'> 
     <thead> 
     <th *ngFor='let column of columns'> 
     {{ column.label }} 
     </th> 
     </thead> 
     <tbody> 
     <tr *ngFor="let record of records"> 
     <td *ngFor='let column of columns'> 
      <ng-container *ngIf="column.template as tmpl; else staticTmpl"> 
      <ng-container *compile="tmpl; context: { record: record }"></ng-container> 
      </ng-container> 
      <ng-template #staticTmpl>{{record[column.field]}}</ng-template> 
     </td> 
     </tr> 
     </tbody> 
    </table> 
    `, 
}) 
export class AdminTableComponent { 
    @Input() columns: any[]; 

    @Input() records: {}[]; 
} 

Plunker Example

も参照してください

@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; 
    } 
} 

AdminComponent

-1

のようなものが存在します。

代わりに、fieldContent関数でテンプレートを解析し、レコードのキーを直接追加することができます。

ここでは、キーが何であれ、{{record [key]}}のすべてのインスタンスを置き換え、Htmlに挿入する補間された文字列を返すregexpを使用する例を示します。

@Component({ 
    selector: 'admin-table', 
    template: ` 
    <table class='table table-bordered'> 
     <thead> 
     <th *ngFor='let column of columns'> 
     {{ column.label }} 
     </th> 
     </thead> 
     <tbody> 
     <tr *ngFor="let record of records"> 
     <td *ngFor='let column of columns' [innerHTML]="fieldContent(column, record) | safeHtml"> 
     </td> 
     </tr> 
     </tbody> 
    </table> 
    `, 
}) 
export class AdminTableComponent { 

    @Input() columns: AdminTableColumn[]; 

    @Input() records: {}[]; 

    fieldContent(column: AdminTableColumn, record: {}) { 
    if (column.template) { 
     let template = column.template; 

     // Go through the keys and replace all isntances in the field. 
     // Note that this is strict and will not replace {{ record.name }} 
     // You may want to add additional regexp to do that. 

     Object.keys(record).forEach(key => { 
     template = template.replace(new RegExp(`{{record.${key}}}`, 'g'), 'some name'); 
     }); 

     return template; 
    } 

    return record[column.field]; 
    } 

} 
+0

あなたの答えに感謝しますが、そのアプローチはすでにそれを破棄しています。なぜなら、テンプレートの中に 'pipe'やその他のコンポーネントを使用することができないからです。それは私が必要とするものをレンダリングするのとほとんど同じです。 – rafrsr

関連する問題