我正在将 Angular 信号与反应形式一起使用,并面临一个问题:当
hasFormControlError
输入信号值发生变化时,validations
和 formControl
计算信号不会更新视图。我在 formControl
信号输入中传递反应式表单控件实例,
这里的问题是计算信号仅在提交时反映视图中的更新,但如果控件是脏的,在按键时无效,即使是错误对象也不会通过计算信号反映在视图中。
但是,如果我将它们更改为吸气剂,它们会正常工作并反映一切。我无法理解为什么会发生这种情况,我在这里做错了。
Stackblitz - https://stackblitz.com/edit/stackblitz-starters-ur795u?file=src%2Fmain.ts
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { fadeAnimation } from '@shared/animations';
import { generateNumericId } from '@shared/utilities';
import { AbstractControl, FormControl } from '@angular/forms';
import { FormControlValidationService } from '../../services';
import { IControlConfig, IFormControlValidation } from '../../models';
import { Component, computed, inject, input, output } from '@angular/core';
@Component({
standalone: true,
selector: 'form-control',
animations: [fadeAnimation],
imports: [CommonModule, FormsModule],
styleUrl: './form-control.component.css',
providers: [FormControlValidationService],
templateUrl: './form-control.component.html'
})
export class FormControlComponent {
private _validationService = inject(FormControlValidationService);
public formControl = input.required<AbstractControl | FormControl>({
alias: 'form-control',
});
public controlConfig = input({}, {
alias: 'control-config',
transform: (value: IControlConfig) => {
return {
isRequired: true,
showErrorMessages: true,
...value
};
}
});
public hasFormControlError = computed<boolean>(() => {
return !!(
(this.formControl().invalid && this.formControl().dirty) ||
(this.controlConfig().submitted && this.formControl().errors)
);
});
public validations = computed<IFormControlValidation[]>(() => {
return Object.keys(this.formControl().errors || {}).map((key) => {
const validationError = {
errorType: key,
errorMessage: '',
id: generateNumericId(),
formControl: this.formControl(),
error: this.formControl().errors?.[key]
};
validationError['errorMessage'] =
this._validationService.getControlErrorMessage(validationError);
return validationError;
});
});
}
我们来看看这个小方法:
public hasFormControlError = computed<boolean>(() => {
return !!(
(this.formControl().invalid && this.formControl().dirty) ||
(this.controlConfig().submitted && this.formControl().errors)
);
});
此方法侦听以下信号的更新:
每当这些更新时,
hasFormControlError
都会重新计算其值。并且仅在这种情况下。
但是,当
this.formControl()
返回的对象的无效字段发生变化时,不会发送任何通知,因为它不是信号,因此无法通知观察者变化。
这同样适用于 dirty
、submitted
和 errors
等字段。
要进一步了解此类场景,您可以参考文章角度信号:保持反应性列车
截至目前,Angular Forms 还没有要观察的信号,但正在向 Angular Forms 添加信号。
要使此功能发挥作用,您可以利用 Angular Forms 提供的
statusChanges
和 valueChanges
可观察量。然后,您可以使用 toSignal()
方法将这些可观察量转换为信号,并在 computed()
内监听结果信号。
即使您选择忽略接收到的值,
computed()
仍会重新计算其值,从而触发更新。这种方法确保 computed()
函数对底层可观察量的变化做出反应。