Reactive forms

Example

Template

<form [formGroup]="searchForm" (ngSubmit)="onFormSubmit()" (reset)="onFormReset()">
  <input formControlName="userName" [style.backgroundColor]="searchForm.controls.userName.dirty && searchForm.controls.userName.errors ? 'red' : 'white'"/>
  <button type="submit" [disabled]="searchForm.invalid">Search</button>
  <button type="reset">Reset</button>
</form>

Component class

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
})
export class FormComponent implements OnInit {
  searchForm = new FormGroup({
    userName: new FormControl('', [Validators.required]),
  });

  private readonly activatedRoute = inject(ActivatedRoute);
  private readonly router = inject(Router);

  readonly queryParamSubscriber = this.activatedRoute.queryParams.pipe(takeUntilDestroyed()).subscribe(queryParams => {
    if (Object.keys(queryParams).length === 0) this.searchForm.reset();
  })

  ngOnInit(): void {
    this.useQueryParams();
  }

  onFormSubmit() {
    console.log('Submit form (dispatch event for effect, call api using a service, etc.)');
    this.updateQueryParams();
  }

  onFormReset() {
    this.searchForm.reset();
  }

  private updateQueryParams() {
    const queryParams = this.searchForm.getRawValue();
    return this.router.navigate([], { queryParams, relativeTo: this.activatedRoute, replaceUrl: true });
  }

  private useQueryParams() {
    const params = this.activatedRoute.snapshot.queryParamMap;
    this.searchForm.controls.userName.setValue((params.get('userName') ?? '').trim());
  }
}