angular / angular/angular

Creating custom CVA based components is STILL almost impossible to in most not-super-basic scenarios (regardless the unified event api)

未關閉
#57,972 7 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
area: forms
主要語言
TypeScript
星號
101k
分支
27.5k
平均合併
1 天 20 小時
30 天內合併 PR
299

描述

### Which @angular/* package(s) are relevant/related to the feature request?

forms

### Description

It is still impossible to implement working custom CVA based components in 50% of scenarios.

Main cause of this is non-existing way how to get ALL information about AbstractControl.

Why?
- there is not any 100% working way how to get information about important control state (valid/invalid/pristine/touched).
- it is important to know control states like valid/invalid/pristine/touched to correctly implement smarter components than hello world

Why current implementation does not work?

- CVA interface does not provide ANY way how to get information about status changes (it can only react to ValueChanges - writevalue and disabled changes - setDisabled), there is not anything like setValid(), setTouched() pristine etc.

- You can get ngControl from injector (because CVA is solving only 20% of domain...) .Control has now "unified events api" https://angular.dev/api/forms/AbstractControl#events unfortunately, it is preserved when {emitEvent: false} during the method calls

- It is EVEN BIGGER Problem as far as disabled control has BOTH valid and invalid SET TO FALSE (lol), so you just DO NOT HAVE ANY way how to get any information about the state of validity, when your control is enabled with {emitEvent:false} (check source code below)

- it is so sad that the only way how to get 100% information about control state is to LISTEN for DOM mutation on Host element (to read ng-invalid, ng-valid, ng-pending, ng-prisitine, etc. classes)
- the same problem when validity of the control changes when the new value is set - you have NO WAY how to get the new valid / invalid status when user patch/set value with emitEvent: false. You cannot even handle this inside of writeValue() because validators are executed after that.... So not any workaround..

FORCING user not to use {emitEvent:false } which is his way to prevent emiting valueChanges "ON THE OUTSIDE SIDE" - aka. consumer of the component (in bigger form) is definitely not a solution to this problem, where Component creator has not any legit way how to get state of the control.

```

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

import { FormControl, PristineChangeEvent, ReactiveFormsModule, StatusChangeEvent, TouchedChangeEvent} from '@angular/forms';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
selector: 'app-root',
standalone: true,
imports: [ReactiveFormsModule, CommonModule],
template: `

Valid: {{number.valid}}
Invalid: {{number.invalid}}
Errors: {{number.errors | json}}

ENABLE



Problems:

  • Disabled input has both VALID and INVALID set TRUE - eventhogh there is no validator and it NO ERRORS

  • When you enable control - it is now valid, but NO events is fired from Control.Events



Events:

    @for(event of events; track $index) {
  • {{event | json}}

  • }

`,
})
export class App {

events: any[] =[];
number = new FormControl();

ngOnInit( ){
this.number.disable();
this.number.events.subscribe(e=> {
if (e instanceof StatusChangeEvent) {
this.events.push("Status - " + e.status);
} else if (e instanceof TouchedChangeEvent) {
this.events.push("Touched - "+ e.touched);
} else if (e instanceof PristineChangeEvent) {
this.events.push("Pristine - "+ e.pristine);
}
}
);
}
}

bootstrapApplication(App);

```

### Proposed solution

- more methods in CVA interface
- event emitter on AbstractControl which emits everytime, regardless the emitEvent settings

### Alternatives considered

- our only WAY how to solve this is to write our own AbstractControl's implementations (inherit the base ones from angular) and to add additional event emiiters...
- in this case where is the main problem the valid/invalid state of control, you can "rebind" your internal valid/invalid/pristine/touched state when setDisabled() of CVA is called.
- in case of changed valid/invalid state when the new value is set to control with emitEvent:false, there is not any way except to "queue" sync check after "writeValue"

image

Just sad state.

貢獻指南

開啟貢獻指南

研究方向

從提供的重現開始,檢查 Angular forms CVA interface、AbstractControl 狀態,以及圍繞 disable/enable 和 emitEvent:false 的 AbstractControl.events 行為。將提議的 CVA methods 和無條件的 AbstractControl event emitter 與現有的 forms APIs 進行比較;done 應透過涵蓋 custom CVA components 中 control validity 和 state visibility 的 tests 來定義。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
angular, typescript
領域
frontend
Issue 類型
功能
難度
5/5
預估耗時
一週以上
活躍度
冷清
描述清晰度
需要釐清
新手友好度
30/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。