Podgląd kątowy 16: wejście komponentowe powiązane z routerem

Ok, to była jedna z funkcji, która najbardziej mnie ekscytowała, ponieważ często piszę dużo kodu, aby zrobić coś bardzo prostego: uzyskać parametry routera. o czym ja mówię? Spójrzmy na przykład.
Załóżmy, że mamy aplikację internetową, a aplikacja internetowa ma opcję takiego parametru routera https://myapp.com/contactForm?name=john&[email protected]
, a przekazanie tych parametrów pozwoliłoby nam automatycznie wypełnić formularz kontaktowy. Jak możemy to osiągnąć?
Stary sposób
Rzućmy okiem na to, jak byśmy to zrobili przed 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
Nowa droga
W momencie pisania tego tekstu aktualna wersja Angular 16 to 16.0.0-rc.2 i właśnie tej wersji będę używać. Rzućmy okiem na dokładnie tę samą funkcjonalność. Zanim przejdziemy do tego, musisz zrobić jedną małą rzecz, zanim to zadziała.
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);
}
}
To pomaga nam na 2 sposoby
- Łatwo się czyta
- Czyści kod, więc nie mamy subskrypcji, którymi musimy zarządzać ręcznie
Jest jednak małe zastrzeżenie w pierwszym punkcie, które zostało poruszone w PR, aby uzyskać tę funkcję.
Dekorator danych wejściowych jest już używany do przekazywania zmiennych do twojego komponentu, więc może to zamącić wodę między parametrami wejściowymi komponentu a parametrami zapytania. Sugerowanym rozwiązaniem tego problemu jest utworzenie nowej nazwy dla dekoratora, który wiąże parametry zapytania. Mamy nadzieję, że ta poprawka zostanie wprowadzona przed wydaniem Angular 16, ale myślę, że zobaczymy.
Jeśli podobał Ci się ten artykuł, wejdź na moją stronę internetową, aby przeczytać ten artykuł i wiele więcej!