Angular 2 compile dynamic template with data

2019-09-04 03:19发布

问题:

I am developing bridge like interface for jquery grid control. The grid is rendered with the below syntax and works as expected.

<t-grid>
  <t-column>...</t-column>
  <t-column>...</t-column>
</t-grid>

While providing support to render template inside the t-column tag, I am able to get the data and jquery element.

jQuery element

<div class="angulartmplbda8aedb-6b16-456d-8c17-3240a674b0c7 angular-template">
   <div _ngcontent-ila-1="">
     <input _ngcontent-ila-1="" type="button" value="Template"></div>
 </div>

Now, the button is displayed with template text. How to dynamically change the input element value which is from gridData.?

 export class TemplateElement {
private context: any;
__parent: tComponents<any, any>; 
constructor(protected el: ElementRef) {
}

ngOnInit() {
    template.render = (self, selector, data, index, prop) => {
        let templateObject = self.angularTemplate;
        if (!templateObject || !templateObject[selector]) {
            templateObject = templateObject || {};
            templateObject[selector] = { key: t.getGuid('angulartmpl'), itemData: [], views: [] };
            self.angularTemplate = templateObject;
        }
        let scope = templateObject[selector];
        if (!t.isNullOrUndefined(index)) {
            if (!scope.itemData)
                scope.itemData = [];
            scope.itemData[index] = data;
        } else {
            scope.itemData = [data];
        }
        let actElement = $(this.el.nativeElement).html();
        let tempElement = "<div class='" + templateObject[selector].key + " t-angular-template'>" + actElement + '</div>';
        return tempElement;
    }
}
ngAfterViewInit() {
    this.compileTempalte();
}

compileTempalte() {
    let element = this.__parent.widget.element;
    let templates = $(element).find('.t-angular-template');
    let templateObject = this.__parent.widget.angularTemplate;
    for (let template in templateObject) {
        let tmplElement = templates.filter('.' + templateObject[template].key);
        if (tmplElement.length) {
            for (let i = 0; i < tmplElement.length; i++) {
               //modified code 
               childView = this.viewContainerRef.createEmbeddedView(this.templateRef, { '$implicit': templateObject[template].itemData[i] });                    
                this.childViews[i] = childView;
                $(tmplElement[i]).append(childView.rootNodes);
            }
        } else {
            delete templateObject[template];
        }
    }
}

clearTempalte() {
    let templateObject = this.__parent.widget.angularTemplate;
    if (templateObject && Object.keys(templateObject).length) {
        for (let tmpl in templateObject) {
            delete templateObject[tmpl];
        }
    }
}
ngOnDestroy(){
    this.clearTempalte()
}

}

回答1:

As discussed, you need to use transclusion:

  • http://toddmotto.com/transclusion-in-angular-2-with-ng-content
  • Creating a dynamic repeater with ng-content transclusion with Angular2

And you need to add let-item="$implicit" on this part:

<template t-template let-item="$implicit">
    <input t-button [value]="item.CustomerID" />
</template>


回答2:

If you want to assign a variable to a property you need to use the bracket syntax:

     <input _ngcontent-ila-1="" type="button" [value]="Template"></div>

The [] means, that the variable Template will be assigned to the value attribute of the input element.

As explained here: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#binding-syntax