angular html日期选择器中的FormControl不报告不存在的日期错误

yhqotfr8  于 6个月前  发布在  Angular
关注(0)|答案(6)|浏览(53)

哪个@angular/*包是bug的来源?

forms

这是一次回归吗?

描述

当一个form-control附加到一个input[type="date"]上时,例如不存在的30.02.2022这样的无效日期可以手动输入而不进入错误状态。
由于它既不报告值也不报告错误,因此无法使用form-control识别已输入无效日期,即使原生输入元素处于无效状态!
控件被认为是valid,其值为null,就好像用户没有填充它一样。
我希望form-control会有一个错误而不是处于valid状态。

请提供一个最小复现bug的链接

https://stackblitz.com/edit/angular-ivy-rqhjhr?file=src/app/app.component.html

请提供您看到的异常或错误

Eventhough the native input element is in an invalid state, the form-control does not report an error or beeing invalid!

请提供您发现此bug的环境(运行ng version)

Angular CLI: 13.3.4
Node: 14.18.2
Package Manager: npm 6.14.15
OS: win32 x64

Angular: 13.3.5
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1303.4
@angular-devkit/build-angular   13.3.4
@angular-devkit/core            13.3.4
@angular-devkit/schematics      13.3.4
@angular/cli                    13.3.4
@schematics/angular             13.3.4
rxjs                            7.5.5
typescript                      4.6.

还有其他信息吗?

  • 无响应*
xxls0lw8

xxls0lw81#

我认为这不是一个Angular 问题。
原生 input[type="date"] 将字符串值返回给 FormControl,而不是 js-Date。FormControls 不检查任何内容。
只在 Chrome 中看到了相同的错误:
https://bugs.chromium.org/p/chromium/issues/detail?id=1020553&q=component%3ABlink%3EForms%3EDate&can=2
例如,Safari 对于无效的日期返回空字符串作为有效日期

inn6fuwd

inn6fuwd2#

浏览器报告原生控件处于无效状态(inputEl.validity.valid),例如,当输入元素填充一个不存在的日期时,css :invalid伪类存在。这是正确的行为,对吗?
这个问题报告了,即使原生元素处于无效状态,Angular FormControl仍然声称它是有效的,但实际上并非如此。
这个问题与浏览器错误有什么关系?我认为这不是问题所在,而是Angular层的一个Bug。

cu6pst1q

cu6pst1q3#

我目前找到的一个解决方法是:

@Directive({
  selector: 'input[type=date][invalidDateInput]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => InvalidDateInputDirective),
      multi: true,
    }
  ],
})
export class InvalidDateInputDirective implements Validator {
  private onChangeCallback?: () => void;

  constructor(
    private element: ElementRef,
  ) {}

  @HostListener('input')
  onInput() {
    this.onChangeCallback?.();
  }

  registerOnValidatorChange(fn: () => void) {
    this.onChangeCallback = fn;
  }

  validate(control: AbstractControl): ValidationErrors | null {
    const input: HTMLInputElement = this.element.nativeElement;
    return input.validity.badInput ? { 'invalid-date-input': 'true' } : null;
  }
}

只需将指令应用于一个输入元素,不存在的日期将导致该元素处于无效状态:

<input type="date" invalidDateInput formControlName="test">
yptwkmov

yptwkmov4#

正如我所说,FormControls doesn't check anything。我的意思是,如果你需要检查浏览器中的原生输入验证,你需要编写自己的验证器。
Angular表单控件仅与输入验证属性一起工作,例如required/max/min ngNativeValidate指令(如果需要)。但它不包括你希望修复的原生ValidityState。
这个问题与浏览器错误有什么关系?
这与在浏览器中以不同方式验证错误日期计数有关。例如:
Chrome设置无效的原生状态:

Safari设置有效的原生状态:

bkhjykvo

bkhjykvo5#

原始的错误报告说这不是一个回归,但是AngularJS检测到了错误的输入并将$invalid设置为true。
某些东西总是在无论ngNativeValidate的情况下,将min/max/required等属性隐含的原生验证传播到控件的valid/errors属性中。那个东西(或者类似的东西)难道不应该同样传播由type=date、type=number等隐含的原生验证吗?这种不一致性(在min和type=number之间,以及在Angular和AngularJS之间)令应用程序开发人员感到惊讶(至少对我来说是这样)。

相关问题