front: stoppe les fuites de souscriptions RxJS (takeUntilDestroyed)
Toutes les souscriptions des composants passent par takeUntilDestroyed(this.destroyRef) : browse, catalog, api-detail, upload, category-form-modal, category-delete-modal. api-detail abandonne le pattern manuel Subscription/ngOnDestroy au profit de DestroyRef (ngOnDestroy ne garde que le clearPoll du setInterval). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,14 +3,15 @@ import {
|
|||||||
signal,
|
signal,
|
||||||
computed,
|
computed,
|
||||||
inject,
|
inject,
|
||||||
|
DestroyRef,
|
||||||
OnInit,
|
OnInit,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { ApiService } from '../../core/api.service';
|
import { ApiService } from '../../core/api.service';
|
||||||
import { CategoryService } from '../../core/category.service';
|
import { CategoryService } from '../../core/category.service';
|
||||||
import { ApiEntry, ApiEntryListItem, Category } from '@datacat/shared';
|
import { ApiEntry, ApiEntryListItem, Category } from '@datacat/shared';
|
||||||
@@ -416,6 +417,7 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
private apiService = inject(ApiService);
|
private apiService = inject(ApiService);
|
||||||
private categoryService = inject(CategoryService);
|
private categoryService = inject(CategoryService);
|
||||||
private fb = inject(FormBuilder);
|
private fb = inject(FormBuilder);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
api = signal<ApiEntry | null>(null);
|
api = signal<ApiEntry | null>(null);
|
||||||
versions = signal<ApiEntryListItem[]>([]);
|
versions = signal<ApiEntryListItem[]>([]);
|
||||||
@@ -462,12 +464,16 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
private pollInterval: ReturnType<typeof setInterval> | null = null;
|
private pollInterval: ReturnType<typeof setInterval> | null = null;
|
||||||
private routeSub: Subscription | null = null;
|
|
||||||
private id = '';
|
private id = '';
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.categoryService.list().subscribe((res) => this.categories.set(res.items));
|
this.categoryService
|
||||||
this.routeSub = this.route.paramMap.subscribe((params) => {
|
.list()
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe((res) => this.categories.set(res.items));
|
||||||
|
this.route.paramMap
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe((params) => {
|
||||||
this.id = params.get('id') ?? '';
|
this.id = params.get('id') ?? '';
|
||||||
this.api.set(null);
|
this.api.set(null);
|
||||||
this.versions.set([]);
|
this.versions.set([]);
|
||||||
@@ -481,7 +487,6 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.routeSub?.unsubscribe();
|
|
||||||
this.clearPoll();
|
this.clearPoll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,11 +503,17 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
onSetCurrent() {
|
onSetCurrent() {
|
||||||
this.settingCurrent.set(true);
|
this.settingCurrent.set(true);
|
||||||
this.apiService.setCurrent(this.id).subscribe({
|
this.apiService
|
||||||
|
.setCurrent(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (entry) => {
|
next: (entry) => {
|
||||||
this.api.set(entry);
|
this.api.set(entry);
|
||||||
this.settingCurrent.set(false);
|
this.settingCurrent.set(false);
|
||||||
this.apiService.getVersions(this.id).subscribe({
|
this.apiService
|
||||||
|
.getVersions(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (v) => this.versions.set(v),
|
next: (v) => this.versions.set(v),
|
||||||
error: () => {},
|
error: () => {},
|
||||||
});
|
});
|
||||||
@@ -513,7 +524,10 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
onRegenerate() {
|
onRegenerate() {
|
||||||
this.regenerating.set(true);
|
this.regenerating.set(true);
|
||||||
this.apiService.regenerate(this.id).subscribe({
|
this.apiService
|
||||||
|
.regenerate(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (entry) => {
|
next: (entry) => {
|
||||||
this.api.set(entry);
|
this.api.set(entry);
|
||||||
this.regenerating.set(false);
|
this.regenerating.set(false);
|
||||||
@@ -568,7 +582,9 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
versionPatch: raw.versionPatch ?? 0,
|
versionPatch: raw.versionPatch ?? 0,
|
||||||
categoryId: raw.categoryId || null,
|
categoryId: raw.categoryId || null,
|
||||||
description: raw.description || null,
|
description: raw.description || null,
|
||||||
}).subscribe({
|
})
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (updated) => { this.api.set(updated); this.savingInfo.set(false); this.editingInfo.set(false); },
|
next: (updated) => { this.api.set(updated); this.savingInfo.set(false); this.editingInfo.set(false); },
|
||||||
error: () => this.savingInfo.set(false),
|
error: () => this.savingInfo.set(false),
|
||||||
});
|
});
|
||||||
@@ -587,7 +603,9 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
contactTechnicalName: raw.contactTechnicalName ?? '',
|
contactTechnicalName: raw.contactTechnicalName ?? '',
|
||||||
contactTechnicalEntity: raw.contactTechnicalEntity ?? '',
|
contactTechnicalEntity: raw.contactTechnicalEntity ?? '',
|
||||||
contactTechnicalEmail: raw.contactTechnicalEmail ?? '',
|
contactTechnicalEmail: raw.contactTechnicalEmail ?? '',
|
||||||
}).subscribe({
|
})
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (updated) => { this.api.set(updated); this.savingContacts.set(false); this.editingContacts.set(false); },
|
next: (updated) => { this.api.set(updated); this.savingContacts.set(false); this.editingContacts.set(false); },
|
||||||
error: () => this.savingContacts.set(false),
|
error: () => this.savingContacts.set(false),
|
||||||
});
|
});
|
||||||
@@ -599,7 +617,10 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
/* Calculer la cible de redirection avant la suppression */
|
/* Calculer la cible de redirection avant la suppression */
|
||||||
const otherVersions = this.versions().filter((v) => v.id !== this.id);
|
const otherVersions = this.versions().filter((v) => v.id !== this.id);
|
||||||
const redirectTarget = otherVersions.find((v) => v.isCurrent) ?? otherVersions[0];
|
const redirectTarget = otherVersions.find((v) => v.isCurrent) ?? otherVersions[0];
|
||||||
this.apiService.delete(this.id).subscribe({
|
this.apiService
|
||||||
|
.delete(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
if (redirectTarget) {
|
if (redirectTarget) {
|
||||||
this.router.navigate(['/catalog', redirectTarget.id]);
|
this.router.navigate(['/catalog', redirectTarget.id]);
|
||||||
@@ -627,17 +648,26 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private loadApi() {
|
private loadApi() {
|
||||||
this.loading.set(true);
|
this.loading.set(true);
|
||||||
this.apiService.get(this.id).subscribe({
|
this.apiService
|
||||||
|
.get(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (entry) => {
|
next: (entry) => {
|
||||||
this.api.set(entry);
|
this.api.set(entry);
|
||||||
this.loading.set(false);
|
this.loading.set(false);
|
||||||
this.startPollIfPending();
|
this.startPollIfPending();
|
||||||
this.apiService.getVersions(this.id).subscribe({
|
this.apiService
|
||||||
|
.getVersions(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (v) => this.versions.set(v),
|
next: (v) => this.versions.set(v),
|
||||||
error: () => {},
|
error: () => {},
|
||||||
});
|
});
|
||||||
if (entry.categoryId) {
|
if (entry.categoryId) {
|
||||||
this.categoryService.browse(entry.categoryId).subscribe({
|
this.categoryService
|
||||||
|
.browse(entry.categoryId)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (data) => this.categoryBreadcrumb.set(data.breadcrumb),
|
next: (data) => this.categoryBreadcrumb.set(data.breadcrumb),
|
||||||
error: () => {},
|
error: () => {},
|
||||||
});
|
});
|
||||||
@@ -658,7 +688,10 @@ export class ApiDetailComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private pollStatus() {
|
private pollStatus() {
|
||||||
this.apiService.get(this.id).subscribe({
|
this.apiService
|
||||||
|
.get(this.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (entry) => {
|
next: (entry) => {
|
||||||
this.api.set(entry);
|
this.api.set(entry);
|
||||||
if (entry.status !== 'PENDING') this.clearPoll();
|
if (entry.status !== 'PENDING') this.clearPoll();
|
||||||
|
|||||||
@@ -327,7 +327,10 @@ export class BrowseComponent implements OnInit {
|
|||||||
loadBrowse() {
|
loadBrowse() {
|
||||||
this.loading.set(true);
|
this.loading.set(true);
|
||||||
this.error.set(null);
|
this.error.set(null);
|
||||||
this.categoryService.browse(this.categoryId()).subscribe({
|
this.categoryService
|
||||||
|
.browse(this.categoryId())
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (data) => {
|
next: (data) => {
|
||||||
this.browseData.set(data);
|
this.browseData.set(data);
|
||||||
this.loading.set(false);
|
this.loading.set(false);
|
||||||
@@ -385,7 +388,9 @@ export class BrowseComponent implements OnInit {
|
|||||||
forkJoin({
|
forkJoin({
|
||||||
apis: this.apiService.list({ search: raw || undefined, page: this.searchPage(), limit: this.searchLimit }),
|
apis: this.apiService.list({ search: raw || undefined, page: this.searchPage(), limit: this.searchLimit }),
|
||||||
categories: this.categoryService.list(raw || undefined),
|
categories: this.categoryService.list(raw || undefined),
|
||||||
}).subscribe({
|
})
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: ({ apis, categories }) => {
|
next: ({ apis, categories }) => {
|
||||||
this.searchResults.set(apis.items);
|
this.searchResults.set(apis.items);
|
||||||
this.searchTotal.set(apis.total);
|
this.searchTotal.set(apis.total);
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import {
|
|||||||
computed,
|
computed,
|
||||||
effect,
|
effect,
|
||||||
inject,
|
inject,
|
||||||
|
DestroyRef,
|
||||||
OnInit,
|
OnInit,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
@@ -154,6 +156,7 @@ import { ApiEntryListItem, ApiType } from '@datacat/shared';
|
|||||||
})
|
})
|
||||||
export class CatalogComponent implements OnInit {
|
export class CatalogComponent implements OnInit {
|
||||||
private apiService = inject(ApiService);
|
private apiService = inject(ApiService);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
apis = signal<ApiEntryListItem[]>([]);
|
apis = signal<ApiEntryListItem[]>([]);
|
||||||
loading = signal(false);
|
loading = signal(false);
|
||||||
@@ -221,6 +224,7 @@ export class CatalogComponent implements OnInit {
|
|||||||
page: this.page(),
|
page: this.page(),
|
||||||
limit: this.limit,
|
limit: this.limit,
|
||||||
})
|
})
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
this.apis.set(res.items);
|
this.apis.set(res.items);
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import {
|
|||||||
signal,
|
signal,
|
||||||
computed,
|
computed,
|
||||||
inject,
|
inject,
|
||||||
|
DestroyRef,
|
||||||
OnInit,
|
OnInit,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { toSignal } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
|
||||||
import { Router, RouterLink, ActivatedRoute } from '@angular/router';
|
import { Router, RouterLink, ActivatedRoute } from '@angular/router';
|
||||||
@@ -507,6 +508,7 @@ export class UploadComponent implements OnInit {
|
|||||||
private categoryService = inject(CategoryService);
|
private categoryService = inject(CategoryService);
|
||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private route = inject(ActivatedRoute);
|
private route = inject(ActivatedRoute);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
step = signal(1);
|
step = signal(1);
|
||||||
selectedFiles = signal<File[]>([]);
|
selectedFiles = signal<File[]>([]);
|
||||||
@@ -628,7 +630,10 @@ export class UploadComponent implements OnInit {
|
|||||||
const preselectedCategoryId = params.get('categoryId');
|
const preselectedCategoryId = params.get('categoryId');
|
||||||
const fromId = params.get('from');
|
const fromId = params.get('from');
|
||||||
|
|
||||||
this.categoryService.list().subscribe({
|
this.categoryService
|
||||||
|
.list()
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
this.categories.set(res.items);
|
this.categories.set(res.items);
|
||||||
if (preselectedCategoryId) {
|
if (preselectedCategoryId) {
|
||||||
@@ -638,11 +643,17 @@ export class UploadComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (fromId) {
|
if (fromId) {
|
||||||
this.apiService.get(fromId).subscribe({
|
this.apiService
|
||||||
|
.get(fromId)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (api) => this.prefillFromApi(api),
|
next: (api) => this.prefillFromApi(api),
|
||||||
error: () => {},
|
error: () => {},
|
||||||
});
|
});
|
||||||
this.apiService.getVersions(fromId).subscribe({
|
this.apiService
|
||||||
|
.getVersions(fromId)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (versions) => this.existingVersions.set(versions),
|
next: (versions) => this.existingVersions.set(versions),
|
||||||
error: () => {},
|
error: () => {},
|
||||||
});
|
});
|
||||||
@@ -748,7 +759,10 @@ export class UploadComponent implements OnInit {
|
|||||||
formData.append('files', f);
|
formData.append('files', f);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.apiService.validate(formData).subscribe({
|
this.apiService
|
||||||
|
.validate(formData)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (result) => {
|
next: (result) => {
|
||||||
this.validating.set(false);
|
this.validating.set(false);
|
||||||
this.validationDone.set(true);
|
this.validationDone.set(true);
|
||||||
@@ -826,7 +840,10 @@ export class UploadComponent implements OnInit {
|
|||||||
formData.append('contactTechnicalEntity', raw.contactTechnicalEntity ?? '');
|
formData.append('contactTechnicalEntity', raw.contactTechnicalEntity ?? '');
|
||||||
formData.append('contactTechnicalEmail', raw.contactTechnicalEmail ?? '');
|
formData.append('contactTechnicalEmail', raw.contactTechnicalEmail ?? '');
|
||||||
|
|
||||||
this.apiService.upload(formData).subscribe({
|
this.apiService
|
||||||
|
.upload(formData)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (entry) => {
|
next: (entry) => {
|
||||||
this.uploading.set(false);
|
this.uploading.set(false);
|
||||||
this.router.navigate(['/catalog', entry.id]);
|
this.router.navigate(['/catalog', entry.id]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, signal, inject, ChangeDetectionStrategy, input, output } from '@angular/core';
|
import { Component, signal, inject, DestroyRef, ChangeDetectionStrategy, input, output } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CategoryService } from '../../core/category.service';
|
import { CategoryService } from '../../core/category.service';
|
||||||
import { CategoryWithCounts } from '@datacat/shared';
|
import { CategoryWithCounts } from '@datacat/shared';
|
||||||
@@ -49,6 +50,7 @@ import { CategoryWithCounts } from '@datacat/shared';
|
|||||||
})
|
})
|
||||||
export class CategoryDeleteModalComponent {
|
export class CategoryDeleteModalComponent {
|
||||||
private categoryService = inject(CategoryService);
|
private categoryService = inject(CategoryService);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
category = input.required<CategoryWithCounts>();
|
category = input.required<CategoryWithCounts>();
|
||||||
confirmed = output<void>();
|
confirmed = output<void>();
|
||||||
@@ -65,7 +67,10 @@ export class CategoryDeleteModalComponent {
|
|||||||
const cat = this.category();
|
const cat = this.category();
|
||||||
this.deleteLoading.set(true);
|
this.deleteLoading.set(true);
|
||||||
this.deleteError.set(null);
|
this.deleteError.set(null);
|
||||||
this.categoryService.delete(cat.id).subscribe({
|
this.categoryService
|
||||||
|
.delete(cat.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.deleteLoading.set(false);
|
this.deleteLoading.set(false);
|
||||||
this.confirmed.emit();
|
this.confirmed.emit();
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import {
|
|||||||
signal,
|
signal,
|
||||||
computed,
|
computed,
|
||||||
inject,
|
inject,
|
||||||
|
DestroyRef,
|
||||||
OnInit,
|
OnInit,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
input,
|
input,
|
||||||
output,
|
output,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CategoryService } from '../../core/category.service';
|
import { CategoryService } from '../../core/category.service';
|
||||||
import { Category } from '@datacat/shared';
|
import { Category } from '@datacat/shared';
|
||||||
@@ -79,6 +81,7 @@ import { Category } from '@datacat/shared';
|
|||||||
})
|
})
|
||||||
export class CategoryFormModalComponent implements OnInit {
|
export class CategoryFormModalComponent implements OnInit {
|
||||||
private categoryService = inject(CategoryService);
|
private categoryService = inject(CategoryService);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
mode = input<'create' | 'edit'>('create');
|
mode = input<'create' | 'edit'>('create');
|
||||||
category = input<Category | null>(null);
|
category = input<Category | null>(null);
|
||||||
@@ -133,7 +136,10 @@ export class CategoryFormModalComponent implements OnInit {
|
|||||||
this.formDescription.set(cat.description ?? '');
|
this.formDescription.set(cat.description ?? '');
|
||||||
} else {
|
} else {
|
||||||
this.formParentId.set(this.parentId());
|
this.formParentId.set(this.parentId());
|
||||||
this.categoryService.list().subscribe({
|
this.categoryService
|
||||||
|
.list()
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe({
|
||||||
next: (res) => this.allCategories.set(res.items),
|
next: (res) => this.allCategories.set(res.items),
|
||||||
error: () => this.allCategories.set([]),
|
error: () => this.allCategories.set([]),
|
||||||
});
|
});
|
||||||
@@ -159,7 +165,7 @@ export class CategoryFormModalComponent implements OnInit {
|
|||||||
? this.categoryService.create({ name, description, parentId: this.formParentId() ?? undefined })
|
? this.categoryService.create({ name, description, parentId: this.formParentId() ?? undefined })
|
||||||
: this.categoryService.update(this.editingCategoryId()!, { name, description });
|
: this.categoryService.update(this.editingCategoryId()!, { name, description });
|
||||||
|
|
||||||
obs.subscribe({
|
obs.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.formLoading.set(false);
|
this.formLoading.set(false);
|
||||||
this.saved.emit();
|
this.saved.emit();
|
||||||
|
|||||||
Reference in New Issue
Block a user