代码之家  ›  专栏  ›  技术社区  ›  Kristian Vitozev

父级中的.getrawvalue()排除了来自FormGroup(窗体自定义窗体控件的一部分)的禁用控件

  •  1
  • Kristian Vitozev  · 技术社区  · 7 年前

    具有实现的组件 ControlValueAccessor 内部的 FormGroup 维护自定义窗体控件的状态。如果有任何领域,那就是其中的一部分 形式群 已禁用,调用时该字段不可见 .getRawValue() 父窗体中的方法。

    根据规范, GeTRAWValuy() 应返回原始对象,包括禁用的字段。

    我查过 GeTRAWValuy() 我发现:

     getRawValue(): any {
        return this._reduceChildren(
            {}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => {
              acc[name] = control instanceof FormControl ? control.value : (<any>control).getRawValue();
              return acc;
            });
      }
    

    所以,基本上,当表单控件是 FormControl (使用自定义表单控件时就是这样,对吗?)它检索 .value 而不是 GeTRAWValuy() 这就是为什么嵌套表单的禁用控件 不包括在内 在最后一个对象中。

    Stackblitz demo

    复制步骤:

    1)单击界面中显示的三个自定义表单控件中的任意一个上的“禁用年份”按钮。

    2)检查以下输出=> GeTRAWValuy() 价值 回答是相同的。

    你知道我怎么克服这个吗?我正在父窗体中查找检索禁用控件的方法。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Eliseo    7 年前

    kav,在自定义表单控件中,

      registerOnChange(fn: (v: any) => void) {
            this.formGroup.valueChanges.subscribe(fn);
        }
    

    所以,组件返回formgroup的“value”。由于控件被禁用,该值不返回此字段。可以更改CustomControl以返回FormGroup的rawValue,因此需要创建onChangeFunction,并在nGoninit中订阅更改并发送rawValues。在订阅时,最好使用takewhile和变量取消订阅

    export class DetailsFields implements ControlValueAccessor,OnInit,OnDestroy {
        ...
        onChange: (v:any) => void = () => {}; //<--define a function
        isAlive:boolean=true; //<--use to unsubscribe, see below
    
        registerOnChange(fn: (v: any) => void) {
          this.onChange = fn; //<--equal to function
        }
    
        //In ngOnInit
        ngOnInit()
        {
          this.formGroup.valueChanges.pipe(takeWhile(()=>this.isAlive))
            .subscribe(v=>{
            //return this.formGroup.getRawValue()
            this.onChange(this.formGroup.getRawValue())
          })
        }
        //In ngOnDestroy
        ngOnDestroy() {  //make isAlive=False to unsubscribe
          this.isAlive=false;
        }
    

    但在这种情况下,您收到的年份总是启用或不启用

    还有另一个问题,那就是没有定制的表单控件,只是管理品牌、年份和颜色的组件。为此,第一个方法是更改应用程序组件,并像使用表单阵列创建另一个表单一样创建表单。

    <div id="cars" [formGroup]="form">
      <div formArrayName="cars">
      <div *ngFor="let car of form.get('cars').controls; let i = index;" 
       [formGroupName]="i">
        <app-details-fields [formGroup]="form.get('cars').at(i)" ></app-details-fields>
      </div>
      </div>
    </div>
    

    在formray中,我们迭代form.get(“cars”).controls,我们需要放置一个[formGroupName]=“i”。在组件中,只需作为输入[FormGroup]Form.get(“cars”)传递到(i)

    当然,您需要更改函数“createCars”以返回一个formGroup。不是返回对象类型make:…,color:…,year的FormControl

    createCar(car: any) {  //return a formGroup,not a formControl
        return this.builder.group({
          make: car.make,
          color: car.color,
          year: car.year
        });
      }
    

    嗯,细节字段变得更容易:

    详细信息-fields.component.ts

    @Component({
      selector: 'app-details-fields',
      templateUrl: './details-fields.component.html',
      styleUrls: ['./details-fields.component.css']  ,
    })
    
    export class DetailsFields {
       @Input() formGroup:FormGroup
    
       disableYear() {
          this.formGroup.get('year').disable();
        }
    
        enableYear() {
          this.formGroup.get('year').enable();
        }
    }
    

    详细信息-fields.component.html

    <div [formGroup]="formGroup">
      <div class="car-wrap">
          <div>
              <p class="title">This car is a {{formGroup.get('make').value}}</p>
          <div>
            <input type="text" formControlName="make">
            <input type="number" formControlName="year">
            <input type="text" formControlName="color">
          </div>
          <div>
            <button style="margin-top: 3px;" (click)="enableYear()">Enable year</button>
            <button style="margin-top: 3px;" (click)="disableYear()">Disable year</button>
          </div>
        </div>
      </div>
    </div>
    
    推荐文章