试图在模板驱动的表单上使用我的Angular 4自定义组件来实现ControlValueAccessor

时间:2017-10-20 21:12:46

标签: angular angular-components angular-reactive-forms angular-template angular-forms

我正在使用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;
              }
            }

请帮忙。

0 个答案:

没有答案