Anteprima di Angular 16: input del componente associato al router

May 02 2023
Ok, questa era una delle funzionalità di cui ero più entusiasta perché spesso mi ritrovo a scrivere molto codice per fare qualcosa di molto semplice: ottenere un parametro del router. Di cosa sto parlando? Diamo un'occhiata a un esempio.

Ok, questa era una delle funzionalità di cui ero più entusiasta perché spesso mi ritrovo a scrivere molto codice per fare qualcosa di molto semplice: ottenere un parametro del router. Di cosa sto parlando? Diamo un'occhiata a un esempio.

Supponiamo di avere un'app Web e l'app Web ha l'opzione per un router param come questo https://myapp.com/contactForm?name=john&[email protected]e il passaggio di questi parametri ci consentirebbe di compilare automaticamente il modulo di contatto. Come potremmo realizzare questo?

Il vecchio modo

Diamo un'occhiata a come lo faremmo prima di Angular 16.

import { CommonModule } from '@angular/common';
import { Component, OnDestroy } from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
} from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-route-one',
  standalone: true,
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  // templateUrl: './route-one.component.html',
  template: `
    <form [formGroup]="contactForm" class="contactForm" (submit)="submit()">
      <input formControlName="firstName" type="text" />
      <input formControlName="email" type="email" />
      <textarea formControlName="comments"></textarea>
      <button>Submit</button>
    </form>
  `,
  styleUrls: ['./route-one.component.scss'],
})
export class RouteOneComponent implements OnDestroy {
  contactForm = new FormGroup({
    firstName: new FormControl(),
    email: new FormControl(),
    comments: new FormControl(),
  });

  private subscription = new Subscription();

  constructor(private route: ActivatedRoute) {
    this.subscription.add(
      route.queryParams.subscribe((params) => {
        const firstName = params['firstName'];
        const email = params['email'];
        const comments = params['comments'];

        if (firstName) this.contactForm.controls.firstName.setValue(firstName);
        if (email) this.contactForm.controls.email.setValue(email);
        if (comments) this.contactForm.controls.comments.setValue(comments);
      })
    );
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  submit() {
    console.log(this.contactForm.value);
  }
}

  • firstName
  • email
  • comments

Il nuovo modo

Al momento della stesura di questo articolo, la versione corrente di Angular 16 è la 16.0.0-rc.2, ed è la versione che userò. Diamo un'occhiata alla stessa identica funzionalità. Prima di poter entrare in questo, c'è una piccola cosa che devi fare prima che funzioni.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'route-one',
    loadComponent: () =>
      import('./route-one/route-one.component').then(
        (m) => m.RouteOneComponent
      ),
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { bindToComponentInputs: true })],
  exports: [RouterModule],
})
export class AppRoutingModule {}

import { CommonModule } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
} from '@angular/forms';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-route-one',
  standalone: true,
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  // templateUrl: './route-one.component.html',
  template: `
    <form [formGroup]="contactForm" class="contactForm" (submit)="submit()">
      <input formControlName="firstName" type="text" />
      <input formControlName="email" type="email" />
      <textarea formControlName="comments"></textarea>
      <button>Submit</button>
    </form>
  `,
  styleUrls: ['./route-one.component.scss'],
})
export class RouteOneComponent implements OnInit {
  @Input() firstName: string;
  @Input() email: string;
  @Input() comments: string;

  contactForm = new FormGroup({
    firstName: new FormControl(),
    email: new FormControl(),
    comments: new FormControl(),
  });

  ngOnInit(): void {
    if (this.firstName)
      this.contactForm.controls.firstName.setValue(this.firstName);
    if (this.email) this.contactForm.controls.email.setValue(this.email);
    if (this.comments)
      this.contactForm.controls.comments.setValue(this.comments);
  }

  submit() {
    console.log(this.contactForm.value);
  }
}

Questo ci aiuta in 2 modi

  1. È facile da leggere
  2. Ripulisce il codice in modo da non avere abbonamenti che dobbiamo gestire manualmente

C'è un piccolo avvertimento sul primo punto, tuttavia, e questo è stato sollevato nel PR per ottenere questa funzione.

Il decoratore di input è già utilizzato per passare le variabili nel componente, quindi questo può confondere l'acqua tra l'input del componente e i parametri di query. La soluzione suggerita per questo è creare un nuovo nome per il decoratore che associa i parametri della query. Si spera che questa correzione venga messa in atto prima del rilascio di Angular 16, ma immagino che vedremo.

Se ti è piaciuto questo articolo, vieni sul mio sito Web per leggere questo articolo e altro!