Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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
Javascript 模板驱动表单中的自定义ControlValueAccessor_Javascript_Angular_Angular2 Template_Angular2 Forms - Fatal编程技术网

Javascript 模板驱动表单中的自定义ControlValueAccessor

Javascript 模板驱动表单中的自定义ControlValueAccessor,javascript,angular,angular2-template,angular2-forms,Javascript,Angular,Angular2 Template,Angular2 Forms,我有一个自定义的组件,它有两种模式:常规模式和禁用模式。这是模板(我对它进行了一些简化,用于演示案例): 以下是自定义ControlValueAccessor组件: import { Component, Input, ViewChild, forwardRef, AfterViewInit, OnInit, OnChanges, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALI

我有一个自定义的
组件,它有两种模式:常规模式和禁用模式。这是模板(我对它进行了一些简化,用于演示案例):

以下是自定义ControlValueAccessor组件

import { Component, Input, ViewChild, forwardRef, 
      AfterViewInit, OnInit, OnChanges, 
      NgModule } from '@angular/core';

import { NG_VALUE_ACCESSOR, NG_VALIDATORS, 
      ControlValueAccessor, FormControl, 
      Validator, NgForm } from '@angular/forms';

 @Component({
   selector: 'data-text-input',
   template: `
   <label  *ngIf="!disabled"
       class="field-label">
       <input class="field-value" 
               [type]="type"
               [required]="required"
               (blur)="onBlur()"
               [(ngModel)]="value"
               #fieldValue="ngModel">
       <span class="field-name">{{ label }}</span>

   </label>
   <div class="field-label" *ngIf="disabled">
       <span class="field-value">{{ value }}</span>
       <span class="field-name">{{ label }}</span>
   </div>
     `,
     providers: [
       {
         provide: NG_VALUE_ACCESSOR,
         useExisting: forwardRef( ()=> DataTextInputComponent ),
         multi: true
       },
       {
         provide: NG_VALIDATORS,
         useExisting: forwardRef( ()=> DataTextInputComponent ),
         multi: true
       }
     ]
   })

   export class DataTextInputComponent implements OnChanges, ControlValueAccessor, Validator  {

@Input() public disabled: boolean = false;
@Input() public label: string;
@Input() public required: boolean = false;
@Input() public type: string = 'text';
@ViewChild('fieldValue') public fieldValue: FormControl;

// infrastructure
public registerOnChange(fn: any) { this.propagateChange = fn; }
public registerOnTouched(fn: any) { this.propagateTouch = fn; }

private propagateChange = (_: any) => { };
private propagateTouch = (_: any) => { };

/**
 * inner value
 */
private innerValue: any = null;

/**
 * on changes hook
 */
public ngOnChanges(): void {
    if ( this.disabled ) {
        this.propagateChange(this.innerValue);
    }
}

/**
 * input events
 */
public onBlur(): void {
    this.propagateChange(this.innerValue);
    this.propagateTouch(true);
}

/**
 * value accessor setter and getter
 */
public get value(): any {
    return this.innerValue;
};

public set value(value: any) {
    if ( value !== 'undefined' ) {
        this.innerValue = value;
        this.propagateChange(value);
        this.propagateTouch(true);
    }
}

/**
 * value accessor implementation
 * @param value 
 */
public writeValue(value: any): void {
    if (value !== this.innerValue) {
        this.innerValue = value;
    }
}

/**
 * validation
 * @param c 
 */
public validate(c: FormControl) {
    return this.errors = (this.disabled) ? null : this.customValidate(c);
}
private customValidate(c: FormControl): {} {
  if ( c.touched ) {
    // some validation logic which is not relevant here;
    return null;
  }
  return null;
}
}
import{Component,Input,ViewChild,forwardRef,
AfterViewInit、OnInit、OnChanges、,
NgModule}来自“@angular/core”;
导入{NG_值存取器、NG_校验器、,
ControlValueAccessor,FormControl,
验证程序,NgForm}来自“@angular/forms”;
@组成部分({
选择器:“数据文本输入”,
模板:`
{{label}}
{{value}}
{{label}}
`,
供应商:[
{
提供:NG_值访问器,
useExisting:forwardRef(()=>DataTextInputComponent),
多:真的
},
{
提供:NG_验证器,
useExisting:forwardRef(()=>DataTextInputComponent),
多:真的
}
]
})
导出类DataTextInputComponent实现OnChanges、ControlValueAccessor、Validator{
@Input()公共禁用:布尔值=false;
@Input()公共标签:字符串;
@Input()public required:boolean=false;
@Input()公共类型:string='text';
@ViewChild('fieldValue')公共字段值:FormControl;
//基础设施
公共注册表更改(fn:any){this.propagateChange=fn;}
公共注册表(fn:any){this.propagateTouch=fn;}
私有更改=((uu:any)=>{};
private-propagateTouch=(uuq:any)=>{};
/**
*内在价值
*/
私有innerValue:any=null;
/**
*上钩
*/
public ngOnChanges():void{
如果(此项已禁用){
this.propagateChange(this.innerValue);
}
}
/**
*输入事件
*/
public onBlur():void{
this.propagateChange(this.innerValue);
这是真的;
}
/**
*值访问器setter和getter
*/
public get value():any{
返回此.innerValue;
};
公共设置值(值:任意){
如果(值!=“未定义”){
this.innerValue=值;
这是一个变化(值);
这是真的;
}
}
/**
*值存取器实现
*@param值
*/
public writeValue(值:any):void{
if(值!==此.innerValue){
this.innerValue=值;
}
}
/**
*验证
*@param c
*/
公共验证(c:FormControl){
返回this.errors=(this.disabled)?null:this.customValidate(c);
}
私有customValidate(c:FormControl):{}{
如果(c.触摸){
//此处不相关的一些验证逻辑;
返回null;
}
返回null;
}
}
表单中还使用了其他组件(如颜色选择器和ng select)

奇怪的是这个。表单值设置正确。没有错误。数据文本输入组件以及表单中的其他组件中的值均正确显示(对于禁用的<代码>和禁用的<代码>!禁用的<代码>)。奇怪的是,当我使用调试器检查
this.profileForm
对象时,
控件
属性具有所有控件及其各自的值,但是表单的
属性忽略了这些控件,其中
禁用
属性(也称为无输入字段)设置为true

这是普朗克:


有什么想法吗?

嗯,这并不明显,直到我找到了将值设置到
AbstractControl.prototype.updateValueAndValidity的方法,结果证明,在这里使用变量名
disabled
是个坏主意:

<form #profileForm="ngForm">
    <data-text-input
          label="lastName"
          [required]="true"
          [disabled]="userIsRegistered"                    
          name="lastName"
          ngModel></data-text-input>
</form>


我已将
disabled
属性重命名为
isReadOnly
,“因为
readonly
也是一个可以在别处检查的属性,也是一个TypeScript界面,而且,塔达,它可以工作。

我在代码中没有看到电子邮件控件。”。你能创建一个plunker来演示你的问题吗?我已经用plunker更新了这个问题,你需要在这里发布所有显示问题的代码,而不是一个明天可以改变或消失的plunker,在将来对任何人都没有帮助:@Rob,你是否因为规则而否决了这个问题?如果是,请再次投票,因为我已经纠正了这两点。我不希望讨论朝着错误的方向发展。你需要在你的物品中添加与解决这个问题相关的任何东西。然后您可以完全移除plunker链接。我没有投反对票
 this._sub = this.dl.selectedEmployee.subscribe( u => {
  if ( u.id ) {
    this.isLoading = false;
      setTimeout( () => {
        this.profileForm.setValue(u);
        this.profileForm.control.markAsPristine();
      }, 10);
  }
});
import { Component, Input, ViewChild, forwardRef, 
      AfterViewInit, OnInit, OnChanges, 
      NgModule } from '@angular/core';

import { NG_VALUE_ACCESSOR, NG_VALIDATORS, 
      ControlValueAccessor, FormControl, 
      Validator, NgForm } from '@angular/forms';

 @Component({
   selector: 'data-text-input',
   template: `
   <label  *ngIf="!disabled"
       class="field-label">
       <input class="field-value" 
               [type]="type"
               [required]="required"
               (blur)="onBlur()"
               [(ngModel)]="value"
               #fieldValue="ngModel">
       <span class="field-name">{{ label }}</span>

   </label>
   <div class="field-label" *ngIf="disabled">
       <span class="field-value">{{ value }}</span>
       <span class="field-name">{{ label }}</span>
   </div>
     `,
     providers: [
       {
         provide: NG_VALUE_ACCESSOR,
         useExisting: forwardRef( ()=> DataTextInputComponent ),
         multi: true
       },
       {
         provide: NG_VALIDATORS,
         useExisting: forwardRef( ()=> DataTextInputComponent ),
         multi: true
       }
     ]
   })

   export class DataTextInputComponent implements OnChanges, ControlValueAccessor, Validator  {

@Input() public disabled: boolean = false;
@Input() public label: string;
@Input() public required: boolean = false;
@Input() public type: string = 'text';
@ViewChild('fieldValue') public fieldValue: FormControl;

// infrastructure
public registerOnChange(fn: any) { this.propagateChange = fn; }
public registerOnTouched(fn: any) { this.propagateTouch = fn; }

private propagateChange = (_: any) => { };
private propagateTouch = (_: any) => { };

/**
 * inner value
 */
private innerValue: any = null;

/**
 * on changes hook
 */
public ngOnChanges(): void {
    if ( this.disabled ) {
        this.propagateChange(this.innerValue);
    }
}

/**
 * input events
 */
public onBlur(): void {
    this.propagateChange(this.innerValue);
    this.propagateTouch(true);
}

/**
 * value accessor setter and getter
 */
public get value(): any {
    return this.innerValue;
};

public set value(value: any) {
    if ( value !== 'undefined' ) {
        this.innerValue = value;
        this.propagateChange(value);
        this.propagateTouch(true);
    }
}

/**
 * value accessor implementation
 * @param value 
 */
public writeValue(value: any): void {
    if (value !== this.innerValue) {
        this.innerValue = value;
    }
}

/**
 * validation
 * @param c 
 */
public validate(c: FormControl) {
    return this.errors = (this.disabled) ? null : this.customValidate(c);
}
private customValidate(c: FormControl): {} {
  if ( c.touched ) {
    // some validation logic which is not relevant here;
    return null;
  }
  return null;
}
}
<form #profileForm="ngForm">
    <data-text-input
          label="lastName"
          [required]="true"
          [disabled]="userIsRegistered"                    
          name="lastName"
          ngModel></data-text-input>
</form>