Как сделать на один компонент несколько роутов и чтобы лишний раз они не перерисовывались, Angular
Набросал пример, код так себе но суть в следующем.
Есть ChildComponent он отображает реактивную форму, которая в последствии может быть заполнена.
После заполнения формы и сохранении ее она закидывается в общий стейт и автоматически должен меняться роут добавляя id к текущему пути. На данный момент при сохранении у нас полностью пересоздается компонент и происходит еле заметное моргание экрана, но если добавить в будущем запрос на сервер то моргание усилится. Как избавиться от такого эффекта и в случае сохранения не перерисовывать компонент, а менять по факту только роут или возможно есть способ просто не перерисовывать один и тот же компонент.
Так же при переходе на роут с неправильным id у нас компонент рендериться 2 раза, хотя по идее просто должна сбрасываться формы и у роута пропадает id
Рутовый модуль Роутинга
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {AppComponent} from "./app.component";
const routes: Routes = [
{
path: '',
component: AppComponent,
loadChildren: () => import('./root/parent.module').then(m => m.ParentModule)
},
{
path: 'child',
loadChildren: () => import('./child/child.module').then(m => m.ChildModule)
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Чилдрен модуль Роутинга
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule, Routes} from "@angular/router";
import {ChildComponent} from "./child.component";
const routes: Routes = [
{
path: '',
component: ChildComponent
},
{
path: ':id',
component: ChildComponent
}
]
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forChild(routes)
],
exports: [RouterModule],
})
export class ChildRoutingModule {
}
Стейт
export interface Card {
id: string;
name: string;
description: string
}
export const STATE: Card[] = [
{
id: '1',
name: 'First',
description: 'First'
}, {
id: '2',
name: 'Second',
description: 'Second'
}
]
Верстка Чилдрен компонента
<a routerLink="/">to Root</a>
<div *ngFor="let item of STATE">
<a [routerLink]="'/child/' + item.id">to {{ item.name }}</a>
</div>
<form
(ngSubmit)="onSubmit()"
[formGroup]="formGroup"
style="display: flex; flex-direction: column; width: 200px"
>
<label>Name:
<input style="display: inline-block; width: 200px; padding: 0; margin: 0; box-sizing: border-box"
formControlName="name">
</label>
<label>Description:
<textarea style="display: inline-block; width: 200px; padding: 0; margin: 0; box-sizing: border-box; resize: none"
formControlName="description"></textarea>
</label>
<button style="width: 100%" type="submit" [disabled]="formGroup.invalid">Submit</button>
</form>
Сам Чилдрен компонент
import {Component, OnDestroy, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {ActivatedRoute, Router} from "@angular/router";
import {STATE} from "../state";
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrl: './child.component.css'
})
export class ChildComponent implements OnInit, OnDestroy {
readonly STATE = STATE;
formGroup: FormGroup = this.formBuilder.group({
name: ['', Validators.required],
description: ['', Validators.required]
});
constructor(
private formBuilder: FormBuilder,
private activatedRoute: ActivatedRoute,
private router: Router) {
}
ngOnInit() {
console.log('ngOnInit')
const id = this.activatedRoute.snapshot.params['id']
if (id) {
const item = STATE.find(el => el.id === id)
if (item) this.formGroup.patchValue(item)
else this.router.navigate(['..'], {relativeTo: this.activatedRoute})
} else {
}
}
ngOnDestroy() {
console.log('ngOnDestroy')
}
onSubmit() {
const id = this.activatedRoute.snapshot.params['id']
if (id) {
const itemIndex = STATE.findIndex(el => el.id === id)
if (itemIndex) {
STATE[itemIndex].id = id.toString()
STATE[itemIndex].name = this.formGroup.value.name
STATE[itemIndex].description = this.formGroup.value.description
}
} else {
const random = Math.floor(Math.random() * 1000000)
STATE.push({
id: random.toString(),
name: this.formGroup.value.name,
description: this.formGroup.value.description
})
this.router.navigate(['./', random], {relativeTo: this.activatedRoute})
}
}
}