如何正确"wrap"包含标签的 Angular 2 组件<template>?



我试图用我自己的组件包装一个组件,在这个例子中是一个primeNG PickList,这样我就可以给它添加一个NgModel属性。我以这个指南作为参考。

所以primeNG picklist允许用户从列表中选择和重新排序项目。

<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值放入我的自定义组件中。本质上,它只是重新定义组件的原始变量并通过代理。它看起来像这样:

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>

所以这工作时,我通过任何@Input@Output值在我的html。它不工作,当我试图"通过"<template>标签与内容,我正在努力找出如何做到这一点。

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

也许这个解决方案对你有用

pick-list-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>

最新更新