无法在 Angular 14 上的 ngFor 中更改输入类型=颜色的值

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

我在角度 ^14.2.0 中使用下面的代码有一个非常奇怪的行为。我无法在第一种形式中更改颜色选择器的输入值,但它在第二种形式中工作得很好。第一种形式的所有其他字段也有效。

app.component.ts

export class AppComponent {
  notWorkingForm: FormGroup = new FormGroup<any>({});
  workingForm: FormGroup = new FormGroup<any>({});
  fieldsDescription: IndicatorEditForm = {
    fields: [
      {
        name: 'period',
        label: 'Period',
        type: 'number',
        value: 20,
      },
      {
        name: 'stdDev',
        label: 'Std. Dev.',
        type: 'number',
        value: 2,
      },
      {
        name: 'color',
        label: 'Color',
        type: 'color',
        value: '#ff0000',
      }
      ]
  }

  foo: Foo = new Foo();

  constructor() {
    this.foo.toForm().fields.forEach(field => {
      this.notWorkingForm.addControl(field.name, new FormControl(field.value));
    });

    this.fieldsDescription.fields.forEach(field => {
      this.workingForm.addControl(field.name, new FormControl(field.value));
    });

    this.workingForm.valueChanges.subscribe(value => {
      console.log('working', value);
    });

    this.notWorkingForm.valueChanges.subscribe(value => {
      console.log('not working', value);
    });
  }
}

class Foo {
  toForm(): IndicatorEditForm {
    return {
      fields: [
        {
          name: 'period',
          label: 'Period',
          type: 'number',
          value: 14,
        },
        {

          name: 'stdDev',
          label: 'Std. Dev.',
          type: 'number',
          value: 2,
        },
        {
          name: 'color',
          label: 'Color',
          type: 'color',
          value: '#cccccc',
        }
      ]
    };
  }
}

export type IndicatorEditForm = {
  fields: IndicatorEditFormField[];
}

export type IndicatorEditFormField = {
  name: string;
  label: string;
  type: IndicatorEditFormFieldType;
  value: any;
  options?: IndicatorEditFormFieldOption[];
}

export type IndicatorEditFormFieldType = 'text' | 'select' | 'number' | 'color';
export type IndicatorEditFormFieldOption = {
  label: string;
  value: any;
}

app.component.html

<h2>Not working</h2>
<form [formGroup]="notWorkingForm" class="row align-items-center">
  <div class="col">
    <div class="row">
      <ng-container *ngFor="let field of foo.toForm().fields">
        <div class="input-group mb-3">
          <span class="input-group-text">{{field.label}}</span>
          <input [type]="field.type" [formControlName]="field.name">
        </div>
      </ng-container>
    </div>
  </div>
</form>

<h2>Working</h2>
<form [formGroup]="workingForm" class="row align-items-center">
  <div class="col">
    <div class="row">
      <ng-container *ngFor="let field of fieldsDescription.fields">
        <div class="input-group mb-3">
          <span class="input-group-text">{{field.label}}</span>
          <input [type]="field.type" [formControlName]="field.name">
        </div>
      </ng-container>
    </div>
  </div>
</form>

如果我只将 ngFor 的右侧切换到“fieldsDescription.fields”并保留表单的初始化,它就会工作。我不知道为什么?我错过了什么?

提前感谢您的帮助。

angular angular-reactive-forms angular-forms
1个回答
0
投票

我想我弄清楚了为什么第一种形式不起作用。这是我不知道 Typescript(我认为更全局的 javascript)如何与原型一起工作的东西。这是因为变量 foo 知道 Foo 类的实例,这个实例表示它有 2 个属性,构造函数和 toForm()。但永远不要问这些属性包含什么!只有当我们执行 foo.toForm() 时,我们才会询问方法内部的内容,在此之前,如果 toForm() 方法返回一个空数组,因为原型知道它必须返回一个数组,但是就这些。

现在 Angular 有了变化检测和 dom 刷新,当 ngFor 第一次执行时,原型只是一个空数组,但在 toForm() 方法加载并公开它的内容之后,ngFor 重新启动以循环遍历数组并加载输入.

当我编辑输入时,Angular 会检测这些输入内部的变化并刷新 dom,它会使用我之前解释的行为为 ngFor 触发另一个循环,清空内容并重新创建输入。在它有时间将新值更新到它的变量之前刷新表单。

顺便说一句,第一种形式的输入周期和 stdDev 也不能很好地工作,我只能在失去焦点之前用键盘设置一个数字,但我之前没有注意到它......

所以为了克服这个问题,我只需要设置一个新的变量,其中包含 toForm() 的内容,并将这个变量用于 ngFor 的右侧,就像 toForm() 的内容已经加载并且 ngFor 不再看到一个带有空数组的原型。

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