Предварительный просмотр Angular 16: вход компонента привязан к маршрутизатору

May 02 2023
Хорошо, это была одна из функций, которая меня больше всего порадовала, потому что я часто пишу много кода, чтобы сделать что-то очень простое: получить параметр маршрутизатора. О чем я говорю? Давайте посмотрим на пример.

Хорошо, это была одна из функций, которая меня больше всего порадовала, потому что я часто пишу много кода, чтобы сделать что-то очень простое: получить параметр маршрутизатора. О чем я говорю? Давайте посмотрим на пример.

Допустим, у нас есть веб-приложение, и в веб-приложении есть опция для параметра маршрутизатора, подобного этому https://myapp.com/contactForm?name=john&[email protected], и передача этих параметров позволит нам автоматически заполнить контактную форму. Как мы можем этого добиться?

По старому

Давайте посмотрим, как бы мы это сделали до 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

Новый путь

На момент написания этой статьи текущая версия Angular 16 — 16.0.0-rc.2, и эту версию я буду использовать. Давайте посмотрим на точно такой же функционал. Прежде чем мы сможем углубиться в это, вам нужно сделать одну небольшую вещь, прежде чем это сработает.

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);
  }
}

Это помогает нам двумя способами

  1. это легко читать
  2. Это очищает код, поэтому у нас нет подписок, которыми мы должны управлять вручную.

Однако есть небольшая оговорка по первому пункту, и она была поднята в PR, чтобы получить эту функцию.

Декоратор ввода уже используется для передачи переменных в ваш компонент, так что это может замутить воду между входными данными компонента и параметрами запроса. Предлагаемое исправление для этого состоит в том, чтобы создать новое имя для декоратора, который связывает параметры запроса. Надеюсь, это исправление будет введено до выпуска Angular 16, но, думаю, посмотрим.

Если вам понравилась эта статья, зайдите на мой сайт , чтобы прочитать эту статью и многое другое!