Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forms): WIP / Proposal, signals in reactive and template driven forms #53481

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gionkunz
Copy link
Contributor

@gionkunz gionkunz commented Dec 10, 2023

This Draft PR proposes adding signals to reactive and template-driven forms. The goal is to collect feedback from the community and the core team.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Currently, Angular forms don't support signals natively. Although through AbstractFormControl, valueChanges and statusChanges can be used together with reactive helpers to extract signals, there are certain drawbacks with this approach:

  • No native feel
  • Boilerplate to convert observables to signals
  • Reactivity was always only partially provided with reactive forms (only values and status changes, not raw values and control state changes like pristine, touched, etc.)
  • Provided the simplicity of the new reactive primitives, it's highly desirable to add a template-driven simple form approach that is backed up with a powerful but straightforward reactive concept.

What is the new behavior?

  • Form controls expose additional signals for each relevant control state, grouped by a new signals property on the control objects.
  • By default, signals are created internally and can be accessed through the control object control.signals.value(). This allows a side-by-side existence with the previous regular form state handling.
  • In ngForm / ngModel based forms, we can't govern the form control creation. Therefore, a different approach was used to pass a new optional signals option to ngFormOptions and ngModelOptions. Using that approach, developers can create their signals in the component and pass them to the template-driven form directives, where they will be added to the respective controls.

Does this PR introduce a breaking change?

  • Yes
  • No

Examples

Signal-based forms (template-driven forms with signals for reactivity)

import { CommonModule } from '@angular/common';
import { Component, computed, effect, signal } from '@angular/core';
import { AbstractControlSignals, FormsModule } from 'angular-signal-forms';

@Component({
  selector: 'app-signal-based-form',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <h1>Simple template driven signal-based form</h1>
    <form #form="ngForm" [ngFormOptions]="{signals}">
      <label>
        First Name:
        <input type="text" required name="firstName" ngModel/>
      </label>
      <label>
        Last Name:
        <input type="text" name="lastName" ngModel/>
      </label>

      <p>Full name: {{ fullName() }}</p>
      @if (showErrors()) {
        <p>Form contains errors</p>
      }
    </form>
  `,
})
export class SignalBasedFormComponent {
  signals = {
    invalid: signal(false),
    dirty: signal(false),
    value: signal({ firstName: '', lastName: '' })
  } satisfies Partial<AbstractControlSignals<{firstName: string; lastName: string}>>;
  fullName = computed(
    () => `${this.signals.value().firstName} ${this.signals.value().lastName}`
  );
  showErrors = computed(
    () => this.signals.invalid() && this.signals.dirty()
  );
  logFullname = effect(() => {
    console.log(`Full name: ${this.fullName()}`);
  });
}

You can check out this Stackblitz with the updated Angular Forms package:
https://stackblitz.com/edit/stackblitz-starters-uyjg2x?file=src%2Freactive-form.component.ts,src%2Ftemplate-driven-form-signals-option.component.ts,src%2Ftemplate-driven-form.component.ts,src%2Fsignal-based-forms.component.ts

Please let me know your feedback on this idea / proposal.

Cheers
Gion

@angular-robot angular-robot bot added the detected: feature PR contains a feature commit label Dec 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
detected: feature PR contains a feature commit
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant