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

Make built-in validator directives standalone #56226

Open
chronospatian opened this issue Jun 2, 2024 · 1 comment
Open

Make built-in validator directives standalone #56226

chronospatian opened this issue Jun 2, 2024 · 1 comment
Labels
area: forms cross-cutting: standalone Issues related to the NgModule-less world
Milestone

Comments

@chronospatian
Copy link

chronospatian commented Jun 2, 2024

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

@angular/forms

Description

I am building a set of configurable form field components that uses the directive composition API. I want to reuse Angular's built-in validator directives to define what validators are applicable to each field without re-implementing them in each form field component.

@Component({
  standalone: true,
  selector: 'form-field[type="project-id"]',
  imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule],
  template: `
    <mat-form-field>
      <mat-label>Project ID</mat-label>
      <input matInput [formControl]="control" />
      @if (control.hasError('required')) {
      <mat-error>Project ID is required</mat-error>
      }
    </mat-form-field>
  `,
  hostDirectives: [{
    directive: RequiredValidator, // TS-992014: Host directive RequiredValidator must be standalone
    inputs: ['required']
  }, {
    directive: FormFieldDirective // implements ControlValueAccessor
  }],
  providers: provideFormField(ProjectIdFieldComponent),
})
export class ProjectIdFieldComponent {
  control = new FormControl();
}
<form-field type="project-id" [(ngModel)]="projectId" [required]="required" />

Related issue: #51248

Proposed solution

Add the standalone flag to existing validator directives.

Alternatives considered

I am currently converting these to standalone directives myself.

@Directive({
  standalone: true,
  providers: [provideValidator(StandaloneRequiredValidator)]
})
export class StandaloneRequiredValidator extends RequiredValidator {}

...etc
@Component({
  hostDirectives: [{
    directive: StandaloneRequiredValidator, // now it works
    inputs: ['required']
  }],
})
export class ProjectIdFieldComponent {}
@JeanMeche
Copy link
Member

JeanMeche commented Jun 17, 2024

Here is a repro showing that it works without the host directive: https://stackblitz.com/edit/angular-standalone-cva-p6pnsn?file=src%2Fmain.ts
The selectors are written to match in a way that they match any FormControl, FormControlName, and NgModel + the dedicated attribute.

Can you provide a real word example where this isn't sufficient ? Thank you.

Edit: Actually MaxValidator, MinValidator, CheckboxRequiredValidator do only match [input].... So the issue is only for those 3 validators. RequiredValidator, PatternValidator, MaxLengthValidator & MinLengthValidators work fine on custom components.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: forms cross-cutting: standalone Issues related to the NgModule-less world
Projects
None yet
Development

No branches or pull requests

3 participants