angular 带有异步验证器的表单事件不会发出StatusChangeEvent,

fd3cxomn  于 10个月前  发布在  Angular
关注(0)|答案(3)|浏览(88)

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

forms

这是一个回归吗?

描述

在特殊情况下,发射状态仍然不起作用。这已经在#41519中报告过,应该修复,但实际上并没有。问题在于Angular在内部调用**_runAsyncValidator**时使用了自己的emitEvent标志,这可能会覆盖之前通过Forms API(pathValue、setValue等)调用的emitEvent选项。在Stackblitz链接中有最小复现情况,但有几个重要的事情:

  1. 有带有一些延迟的asyncValidator
  2. 模板中有formGroup和formControlName(如果没有formControlName指令,它将起作用)
  3. patchValue在@input setter中被调用 - 如果在ngOnInit中调用,它将起作用 - 因为Angular会多次调用updateValueAndValidity,这个设置可能导致了底部描述的情况。
    @JeanMeche的实际实现应该通过将这些事件传递到新的事件流中来解决这个问题。我认为这个实现仍然存在问题,因为主要的问题是某些内容可以在不通知订阅者的情况下在内部更改表单状态,但尽管如此,我相信它仍然无法按预期工作。
    此外,reichemn在这里指出文档不正确。在当前实现中,有一个新的内部标志shouldHaveEmitted,它应该包含有关是否某些手动调用API请求emitEvent的信息,但问题是它仅基于emitEvent标志,而不是shouldHaveEmitted标志。因此,如果有多个调用updateValueAndValidity和带有emitEvent标志的异步调用,它们会取消emitEvent信息。如果只有一个带有emitEvent false的手动调用,那么它是可以接受的。
    因此,这种情况将破坏这种行为:
  4. 触发updateValueAndValidity的手动调用 - form.patchValue({}, {emitEvent: true})
  5. 触发updateValueAndValidity并将emitEvent设置为false的内部调用 - 这将取消先前的asyncValidatorSubscription,并且由于emitEvent为true,将继续使用shouldHaveEmitted设置为true
  6. 触发updateValueAndValidity并将emitEvent设置为false的内部调用 - 这将取消先前的asyncValidatorSubscription,并且由于emitEvent为false,将继续使用shouldHaveEmitted设置为false
  7. 结果是先前关于应发出事件的信息完全被框架内部调用所丢失。
    看起来这个小小的改变(当还从已取消的订阅中获取shouldHaveEmitted时)可能会解决这个问题。我只修改了这两行代码:
    shouldHaveEmitted: shouldHaveEmitted !== false

    const shouldHaveEmitted = (this._hasOwnPendingAsyncValidator?.emitEvent || this._hasOwnPendingAsyncValidator?.shouldHaveEmitted) || ?? false;
mctunoxg

mctunoxg1#

有些事情真的很奇怪。

bbmckpt7

bbmckpt72#

你好,你能检查一下stackblitz复现是否展示了你描述的问题吗?
从我看到的来看,observables在每次输入更新时都会发出PENDING,然后是VALID

6ovsh4lw

6ovsh4lw3#

这是奇怪的。是的,我又检查了一遍。我正在附上GIF。如果你在输入下方看不到任何东西,那意味着它不起作用,因为那里应该是有效的。如果你取消注解this.patchWithDelay(value); ,它将显示正确的值-有效。输入更新是没有问题的,没有问题。问题在于当你尝试通过调用patchValue在输入中设置值时。

$Example$

相关问题