如何正确地包装&#34;一个包含<template>标签的Angular 2组件?

时间:2016-10-28 22:42:48

标签: angular angular2-template angular2-forms primeng

我试图用我自己的组件包装一个组件,在这种情况下是一个primeNG PickList,这样我就可以为它添加一个NgModel属性。我正在关注this guide as my reference

因此,primeNG选项列表允许用户从列表中选择和重新排序项目。

<p-pickList [source]="list1" [target]="list2">
    <template let-car>
        <div class="ui-helper-clearfix">
            <img src="showcase/resources/demo/images/car/{{car.brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/>
            <div style="font-size:14px;float:right;margin:15px 5px 0 0">{{car.brand}} - {{car.year}} - {{car.color}}</div>
        </div>
    </template>
</p-pickList>

所以我希望能够将上述内容包装在我自己的组件中

我试着靠自己做这件事。我的方法是将原始组件的@Input@Output@ContentChild值放入我的自定义组件中。实质上它只是redefining the original variables of the component and proxying it through。所以它看起来像这样:

import {
    Component, OnInit, Input, forwardRef, Output, EventEmitter,
    ContentChild, TemplateRef
} from '@angular/core';
import {
    ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR,
    NG_VALIDATORS
} from '@angular/forms';

@Component({
    selector: 'form-primeng-picklist',
    template: `
    <p-pickList [source]="source"
        [target]="target" [responsive]="responsive" [showSourceControls]="showSourceControls" 
        [showTargetControls]="showTargetControls" (onMoveToTarget)="onMoveToTarget"
        (onMovetoSource)="onMovetoSource" [sourceStyle]="sourceStyle" [targetStyle]="targetStyle">
        <template [pTemplateWrapper]="itemTemplate" ></template>
    </p-pickList>
    `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => PickListFormComponent), multi: true
        },
        {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => PickListFormComponent), multi: true
        }
    ],
})
export class PickListFormComponent implements ControlValueAccessor {

    @Input() source: any[];
    @Input() target: any[];
    @Input() sourceHeader: string;
    @Input() targetHeader: string;
    @Input() responsive: boolean;
    @Input() style: any;
    @Input() styleClass: string;
    @Input() sourceStyle: any;
    @Input() targetStyle: any;
    @Input() showSourceControls: boolean = true;
    @Input() showTargetControls: boolean = true;
    @Output() onMovetoSource: EventEmitter<any> = new EventEmitter();
    @Output() onMoveToTarget: EventEmitter<any> = new EventEmitter();
    @ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;

    propagateChange: any = () => { };
    validateFn: any = () => { };

    constructor() { }

    /**
     * Write a new value to the element.
     */
    writeValue(value: any): void {
        if (value) {
            console.log('VALUE IS = ' + JSON.stringify(value));
            this.target = value;
        }
    }
    /**
     * Set the function to be called when the control receives a change event.
     */
    registerOnChange(fn: any): void {
        this.propagateChange = fn;
    }
    /**
     * Set the function to be called when the control receives a touch event.
     */
    registerOnTouched(fn: any): void {

    }

    validate(c: FormControl) {
        return this.validateFn(c);
    }
}

示例用法(失败)

<form-primeng-picklist
    [source]="myList" [target]="artifactorySelectedList" [responsive]="true" [showSourceControls]="false"
    [showTargetControls]="false" (onMoveToTarget)="addChecksums($event)" (onMovetoSource)="removeChecksums($event)"
    [sourceStyle]="{'height':'300px'}" [targetStyle]="{'height':'300px'}"
    [(ngModel)]="testPickList" name="testPickList">
            <template let-artifact>
            <div class="ui-grid" style="border-bottom:1px solid #D5D5D5;">
                <div class="ui-grid-row">
                    <div class="ui-grid-col-1" style="text-align:center">
                        <span><i class="fa fa-archive fa-3x" aria-hidden="true"></i></span>
                    </div>
                    <div class="ui-grid-col-11">
                        <span><strong>Name:</strong> {{artifact.artifact}}</span>
                        <span><strong>Revision:</strong> {{artifact.revision}}</span>
                        <strong>Organisation:</strong> {{artifact.organisation}}
                        <strong>Branch:</strong> {{artifact.branch}}
                    </div>
                </div>
            </div>
        </template>
</form-primeng-picklist>

因此,当我在html中传递任何@Input@Output值时,这会有效。 当我尝试通过&#39;带有内容的<template>标记,我正在努力弄清楚如何执行此操作。

所以一般的问题是如何正确包装允许您使用<template>标签的自定义组件? (没有渲染)

1 个答案:

答案 0 :(得分:1)

也许这个解决方案适合你

<强>接一览form.component.ts

替换

<template [pTemplateWrapper]="itemTemplate" ></template>

<template let-item>
  <template [pTemplateWrapper]="itemTemplate" [item]="item"></template>
</template>

因此,您的模板应如下所示:

<p-pickList ...>
  <template let-item>
    <template [pTemplateWrapper]="itemTemplate" [item]="item"></template>
  </template>
</p-pickList>