Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尝试使用在模板驱动窗体上实现ControlValueAccessor的Angular 4自定义组件_Angular_Angular Components_Angular Reactive Forms_Angular Template_Angular Forms - Fatal编程技术网

尝试使用在模板驱动窗体上实现ControlValueAccessor的Angular 4自定义组件

尝试使用在模板驱动窗体上实现ControlValueAccessor的Angular 4自定义组件,angular,angular-components,angular-reactive-forms,angular-template,angular-forms,Angular,Angular Components,Angular Reactive Forms,Angular Template,Angular Forms,我正在使用Angular 4.3.6和typescript版本2.20。我已经创建了一个Angular 4自定义组件,它实现了ControlValueAccessor,并希望在我的一个模板驱动表单上使用它,但当我尝试此操作时,自定义组件的writeValue和registerOnChange事件不会触发。我以前创建过一个自定义组件,它们在被动表单上工作得很好,所以我想知道是否有可能在模板驱动的表单上使用实现ControlValueAccessor的自定义组件。这可能吗?如果是,我做错了什么?(我

我正在使用Angular 4.3.6和typescript版本2.20。我已经创建了一个Angular 4自定义组件,它实现了ControlValueAccessor,并希望在我的一个模板驱动表单上使用它,但当我尝试此操作时,自定义组件的writeValue和registerOnChange事件不会触发。我以前创建过一个自定义组件,它们在被动表单上工作得很好,所以我想知道是否有可能在模板驱动的表单上使用实现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;
              }
            }
import{Component,OnInit,ViewChild,OnDestroy,Output,EventEmitter,Input,forwardRef}来自“@angular/core”;
从“@angular/forms”导入{ControlValueAccessor,NG_VALUE_ACCESSOR};
从“@angular/platform browser”导入{domsanizer}
从“../../services/common.service”导入{CommonService};
从“./config layout.service”导入{ConfigLayoutService};
@组成部分({
选择器:“配置布局”,
模板:'
    • {{configlayout.Name}
', 供应商:[ { 提供:NG_值访问器, useExisting:forwardRef(()=>ConfigLayoutComponent), 多:真的 }, ConfigLayoutService ] }) 导出类ConfigLayoutComponent实现OnInit、OnDestroy、ControlValueAccessor { @Output()itemChanged:EventEmitter=新的EventEmitter(); @Input()公共数据:任意[]; @输入('IsCabinet')\u IsCabinet:boolean=false; //稍后提供的回调的占位符 //通过控制值访问器 私有onTouchedCallback:()=>{}; 私有onChangeCallback:((_quo:any)=>{}; @输入()获取值():任意 { 返回this.configLayoutService.configLayoutValue; } 设定值(val:any) { this.configLayoutService.configLayoutValue=val; if(this.onChangeCallback) { 这个.onChangeCallback(val); } } 构造函数(专用清理器:DOMSANTIZER,专用commonService:commonService,专用configLayoutService:configLayoutService) { } ngOnInit():void { 如果(!this.value) { this.configLayoutService.configLayoutValue={}; } } ngOnChanges(输入:任意):无效 { if(该值) { if(this.onChangeCallback) { this.onChangeCallback(this.value); } } } writeValue(值:任意):无效 { 如果(值) { 这个值=值; } } 注册变更(fn:任何):无效 { this.onChangeCallback=fn; } 注册人(fn:任何):无效 { this.onTouchedCallback=fn; } 恩贡德斯特罗() { this.value=未定义; } 获取imgFileName():任意 { let name:string=“”; 如果(this.value!=null) { name=this.value.ImageFileName; } 返回名称; } get-liBackgroundImageStyle():任意 { let style:any=this.sanitizer.bypassSecurityTrustStyle(“宽度:348px;高度:211px;页边顶部:5px!重要;边框顶部:灰色1px实心;背景:url(CoreIVCli/src/layoutimages/“+this.imgFileName+”)无重复;”; 回归风格; } 获取showImage():布尔值 { 让我们看看:布尔=假; 如果(this.value!=null) { show=this.value.ImageFileName!=null; } 回归演出; } layoutChanged(配置:任意) { this.itemChanged.emit(配置); } 获取configLabel():字符串 { let标签:string=“Rack”; 如果(这是一个数据库) { label=“机柜”; } 退货标签; } trackByLayouts(索引:number,配置:any) { 返回config.Id; } }

请提供帮助。

为什么在组件中使用ControlValueAccessor?这样我的组件就可以绑定到ngModel,所以当单击单选按钮时,组件的值将通过ngModel使用所选单选按钮的值进行更新。ControlValueAccessor主要是Angular forms API和DOM中本机元素之间的桥梁。我认为使用ControlValueAccess不是一个好主意