Angular - 可重用的表单组选择组件无法设置默认值

问题描述 投票:0回答:1

我有角度可重用选择组件,它接受

formControlName
作为
@Input
。并渲染选择组件,选项作为子组件传递并在内部渲染
<ng-content>

select.component.ts

import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {faChevronDown} from '@fortawesome/pro-solid-svg-icons';

@Component({
  selector: 'component-select',
  templateUrl: './select.component.html',
  styleUrls: ['./select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => SelectComponent),
    }
  ]
})
export class SelectComponent implements OnInit {
  @Input() formControlName: string;
  public formControl: FormControl = new FormControl();

  public onChange: (_: any) => void = () => {};
  public onTouched: () => void = () => {}


  constructor() {
  }

  ngOnInit(): void {
  }

   writeValue(obj: any): void {
         this.formControl.setValue(obj);
    }
  registerOnChange(fn: any): void {
        this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(disabled: boolean): void {
    disabled ? this.formControl.disable() : this.formControl.enable();
  }

  protected readonly faChevronDown = faChevronDown;
}

select.component.html

<component-label><ng-content select="[slot=label]"></ng-content></component-label>
<div class="input-container">
  <div class="left-icon"> <ng-content select="[slot=left-icon]"></ng-content></div>
  <select class="form-input highlight-on-error" [formControl]="formControl" (change)="onChange(formControl.value)" >
    <ng-content></ng-content>
  </select>
  <div class="right-icon"><fa-icon [icon]="faChevronDown"></fa-icon></div>
</div>
<component-error-message [controlName]="formControlName"></component-error-message>

该组件的使用很简单,它会从 FormGroup 接收表单控件作为 formControlName,在某些情况下表单控件会设置默认值。在这种情况下,

writeValue
将接收 obj 作为参数,并且它被正确传递,但
setValue
不会被调用,并且 select 具有空值。

用法

this.formBuilder.group({
      nationality: [this.entry?.nationality === '' ? null : this.entry?.nationality]
    });

<component-select formControlName="nationality">
      <ng-container slot="label">{{ 'NATIONALITY_LABEL' | translate }}</ng-container>
      <option [ngValue]="null"></option>
      <option [ngValue]="option.code" *ngFor="let option of countries$ | async">{{ option.name }}</option>
    </component-select>

问题是如果条目有国籍,那么它应该设置该值。目前尚未设置。如果在组件初始化之前加载值,我应该更改选择组件逻辑的哪一部分来设置值?

javascript angular angularjs
1个回答
0
投票

使用自定义表单组件时,无需读取表单控件名称和其他操作,一切都是自动的,我们所需要做的就是以正确的格式配置组件!

import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {faChevronDown} from '@fortawesome/pro-solid-svg-icons';

@Component({
  selector: 'component-select',
  template: `
<component-label><ng-content select="[slot=label]"></ng-content></component-label>
<div class="input-container">
  <div class="left-icon"> <ng-content select="[slot=left-icon]"></ng-content></div>
  <select class="form-input highlight-on-error" [value]="value"
     [disabled]="disabled"
     (focus)="markAsTouched()"
     (change)="onChange(formControl.value)" >
    <ng-content></ng-content>
  </select>
  <div class="right-icon"><fa-icon [icon]="faChevronDown"></fa-icon></div>
</div>
<component-error-message [controlName]="formControlName"></component-error-message>
  `,
  styleUrls: ['./select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => SelectComponent),
    }
  ]
})
export class SelectComponent implements OnInit {
  value: any;

  onChange = (quantity) => {};

  onTouched = () => {};

  touched = false;

  disabled = false;

  writeValue(value: any) {
    this.value = value;
  }

  registerOnChange(onChange: any) {
    this.onChange = onChange;
  }

  registerOnTouched(onTouched: any) {
    this.onTouched = onTouched;
  }

  markAsTouched() {
    if (!this.touched) {
      this.onTouched();
      this.touched = true;
    }
  }

  setDisabledState(disabled: boolean) {
    this.disabled = disabled;
  }

  protected readonly faChevronDown = faChevronDown;
}

即使上面的代码片段不起作用,请阅读这些文章以了解有关此方法的更多信息

Angular 反应式表单:自定义表单控件 — 控制值访问器(推荐!)

Angular 自定义表单控件:完整指南

© www.soinside.com 2019 - 2024. All rights reserved.