如何正确 "wrap" 包含 <template> 标签的 Angular 2 组件?
How to properly "wrap" an Angular 2 component that contains <template> tags?
我正在尝试用我自己的组件包装一个组件,在这种情况下是一个 primeNG PickList,以便我能够向它添加一个 NgModel 属性。我正在关注 this guide as my reference.
因此,primeNG 选择列表允许用户select 和重新排序列表中的项目。
<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
值时,这会起作用。 当我尝试 'pass through' 带有内容 的 <template>
标签时它不起作用,我正在努力弄清楚如何做到这一点。
所以一般的问题是 如何正确包装允许您使用 <template>
标签的自定义组件? (没有渲染)
也许这个解决方案对你有用
选择列表-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>
我正在尝试用我自己的组件包装一个组件,在这种情况下是一个 primeNG PickList,以便我能够向它添加一个 NgModel 属性。我正在关注 this guide as my reference.
因此,primeNG 选择列表允许用户select 和重新排序列表中的项目。
<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
值时,这会起作用。 当我尝试 'pass through' 带有内容 的 <template>
标签时它不起作用,我正在努力弄清楚如何做到这一点。
所以一般的问题是 如何正确包装允许您使用 <template>
标签的自定义组件? (没有渲染)
也许这个解决方案对你有用
选择列表-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>