angular / angular

Deliver web apps with confidence 🚀
https://angular.dev
MIT License
95.73k stars 25.27k forks source link

Proposal for even better typings FormGroup.value #57244

Closed StephenSPaul closed 1 month ago

StephenSPaul commented 1 month ago

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

forms

Description

I absolutely love Angular forms, and now with typed forms, it is arguably one of Angular's strongest USPs, so THANK YOU!

At the moment, FormGroup.value returns a Partial<T> because any of the controls may be disabled, and therefore may be undefined. This has already been noted with https://github.com/angular/angular/issues/46341. FormControl.value should also therefore return T | undefined but I digress...

I would like an option to instantiate a FormControl / FormGroup that restricts whether it (or any of its children) can subsequently be enabled/disabled or not. This will have the benefit of creating more accurate typings for formGroup.value where only 'disableable' controls can have a possible undefined value.

Proposed solution

The enable() / disable() methods should only be available on a control if it holds a value of type T | undefined. Also, if a control was constructed with the disabled: boolean property set, it's type should be inferred as T | undefined. This will also facilitate more accurate typings for FormGroup.value where only those fields which are 'disableable' may hold a value of T | undefined while all other fields may only hold a value of type T. Here is an example illustrating the desired behaviour:

import { inject } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms';

class MyComponent {

  readonly formBuilder = inject(FormBuilder);

  readonly fg = this.formBuilder.group({
    firstName: new FormControl(''), // string
    lastName: new FormControl({ value: '', disabled: false }), // string | undefined
    age: new FormControl({ value: 0, disabled: true }), // number | undefined
    gender: '', // string
    bio?: '' // string | undefined
  }, {
    strictControlDisabling: true // <-- NEW PROPOSED OPTION. NAME COULD BE IMPROVED
  })

  updateControlsState() {
    this.fg.controls.firstName.disable() // Error: Property 'disable' does not exist on type
    this.fg.controls.lastName.disable() // OK
    this.fg.controls.age.enable() // OK
    this.fg.controls.gender.enable() // Error: Property 'enable' does not exist on type
    this.fg.controls.bio.disable() // OK
  }

  getFormValue() { // should return { firstName: string, lastName?: string, age?: number, gender: string, bio?: string } 
    return this.fg.value;
  }
}
JeanMeche commented 1 month ago

Hi, basically this is the same request as #47834, let's continue tracking this over there.

angular-automatic-lock-bot[bot] commented 2 weeks ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.