我正在使用Angular 4.3.6和typescript版本2.20。我创建了一个实现ControlValueAccessor的Angular 4自定义组件,并希望在我的一个模板驱动表单上使用它,但是当我尝试这个时,自定义组件的writeValue和registerOnChange事件不会触发。我之前创建了一个自定义组件,它们在Reactive表单上运行良好,所以我想知道是否可以在模板驱动的表单上使用实现ControlValueAccessor的自定义组件。这可能吗?如果是这样,我做错了什么? (我已经编辑了这篇文章,因为我现在对这个问题有了更清楚的认识。)下面是我的代码:
import { Component, OnInit, ViewChild, OnDestroy, Output, EventEmitter, Input, forwardRef } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import { DomSanitizer } from '@angular/platform-browser'
import { CommonService } from '../../services/common.service';
import { ConfigLayoutService } from './config-layout.service';
@Component({
selector: 'config-layout',
template: '<div>
<ul class="clean-list">
<li>
<ul class="clean-list" style="height:175px; overflow:auto">
<li *ngFor="let configlayout of data; trackBy: trackByLayouts | filter:[{Disabled: false}]">
<label class="input-control radio small-check" style="margin-right:5px!important">
<input type="radio" [value]="configlayout" name="cl" [(ngModel)]="value" (ngModelChange)="layoutChanged($event)" />
<span class="check"></span>
<span class="caption" title="{{configlayout.Description}}">{{configlayout.Name}}</span>
</label>
</li>
</ul>
</li>
<li [title]="value.Description" *ngIf="showImage" [style]="liBackgroundImageStyle">
</li>
</ul>
</div>',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ConfigLayoutComponent),
multi: true
},
ConfigLayoutService
]
})
export class ConfigLayoutComponent implements OnInit, OnDestroy, ControlValueAccessor
{
@Output() itemChanged: EventEmitter<ConfigLayoutComponent> = new EventEmitter<ConfigLayoutComponent>();
@Input() public data: any[];
@Input('IsCabinet') _IsCabinet: boolean = false;
//Placeholders for the callbacks which are later provided
//by the Control Value Accessor
private onTouchedCallback: () => {};
private onChangeCallback: (_: any) => {};
@Input() get value(): any
{
return this.configLayoutService.configLayoutValue;
}
set value(val: any)
{
this.configLayoutService.configLayoutValue = val;
if (this.onChangeCallback)
{
this.onChangeCallback(val);
}
}
constructor(private sanitizer: DomSanitizer, private commonService: CommonService, private configLayoutService: ConfigLayoutService)
{
}
ngOnInit(): void
{
if (!this.value)
{
this.configLayoutService.configLayoutValue = {};
}
}
ngOnChanges(inputs: any): void
{
if (this.value)
{
if (this.onChangeCallback)
{
this.onChangeCallback(this.value);
}
}
}
writeValue(value: any): void
{
if (value)
{
this.value = value;
}
}
registerOnChange(fn: any): void
{
this.onChangeCallback = fn;
}
registerOnTouched(fn: any): void
{
this.onTouchedCallback = fn;
}
ngOnDestroy()
{
this.value = undefined;
}
get imgFileName(): any
{
let name: string = "";
if (this.value != null)
{
name = this.value.ImageFileName;
}
return name;
}
get liBackgroundImageStyle(): any
{
let style: any = this.sanitizer.bypassSecurityTrustStyle("width:348px;height:211px;margin-top:5px!important;border-top: grey 1px solid; background: url(CoreIVCli/src/layoutimages/" + this.imgFileName + ") no-repeat;");
return style;
}
get showImage(): boolean
{
let show: boolean = false;
if (this.value != null)
{
show = this.value.ImageFileName != null;
}
return show;
}
layoutChanged(config: any)
{
this.itemChanged.emit(config);
}
get configLabel(): string
{
let label: string = "Rack";
if (this._IsCabinet)
{
label = "Cabinet";
}
return label;
}
trackByLayouts(index: number, config: any)
{
return config.Id;
}
}
请帮忙。