Implementacja okien dialogowych formularzy Upsert w Angular
Wiele aplikacji wymaga możliwości tworzenia i aktualizowania rekordów za pośrednictwem interfejsu użytkownika. Zwykle będziemy chcieli użyć tego samego komponentu okna dialogowego dla obu operacji. Termin „upsert” jest połączeniem słów „update” i „insert” i odnosi się do faktu, że w oknie dialogowym można utworzyć nowy rekord lub zaktualizować istniejący.
Zobaczmy, jak możemy zaimplementować tę funkcjonalność. Ja skorzystam z ngneat/dialogbiblioteki, ale ty możesz użyć czego chcesz. Najpierw utworzymy wspólny interfejs data, który musimy przekazać do naszego okna dialogowego:
export interface UpsertDialogData<T> {
action: 'add' | 'edit';
actions$: Record<
UpsertDialogData['type'],
(value: T) => Observable<any>
>;
currentValue: T | undefined;
}
Teraz utwórzmy podstawowy upsertkomponent okna dialogowego:
import { DialogRef } from '@ngneat/dialog';
import { loadingFor } from '@ngneat/loadoff';
import { HotToastService } from '@ngneat/hot-toast';
@Directive()
export abstract class UpsertDialogComponent<Entity extends Record<string, any>>
implements OnInit
{
private toast = inject(HotToastService);
loader = loadingFor('upsert');
ref: DialogRef<UpsertDialogData<Entity>> = inject(DialogRef);
abstract get form(): FormGroup;
abstract getMessages(): Record<UpsertDialogData['action'], string>;
get action() {
return this.ref.data.action;
}
ngOnInit() {
if (this.ref.data.action === 'edit') {
this.form.patchValue(this.ref.data.currentValue);
}
}
upsert() {
if (this.form.invalid) return;
this.ref.data.actions$[this.action](this.form.getRawValue())
.pipe(this.loader.upsert.track())
.subscribe(() => {
this.ref.close();
this.toast.success(this.getMessages()[this.action]);
});
}
}
Użyjmy naszej klasy bazowej i utwórzmy okno dialogowe do wstawiania użytkownika:
import { errorTailorImports } from '@ngneat/error-tailor';
@Component({
standalone: true,
imports: [errorTailorImports],
templateUrl: `./upsert-user-dialog.component.html`
})
export class UpsertUserDialogComponent extends UpsertDialogComponent<User> {
form = inject(FormBuilder).nonNullable.group({
name: ['', Validators.required],
});
getMessages() {
return {
add: `User was added successfully`,
edit: `User was updated successfully`,
};
}
}
<header>
<h3>{{ action === 'edit' ? 'Edit User' : 'New User' }}</h3>
</header>
<div>
<form [formGroup]="form" errorTailor>
<input
placeholder="Name"
formControlName="name" />
</form>
</div>
<footer>
<button dialogClose>Cancel</button>
<button
[loading]="loader.upsert.inProgress$ | async"
(click)="upsert()"
>
{{ action === 'edit' ? 'Save' : 'Create' }}
</button>
</footer>
@Component({
template: `
<button (click)="openUpsertUserDialog('add')">Add User</button>
<-- ngFor -->
<button (click)="openUpsertUserDialog('edit', user)">Edit</button>
`
})
export class UsersPageComponent {
openUpsertUserDialog(
action: UpsertDialogData['action'],
currentValue?: UpsertDialogData<User>['currentValue']
) {
this.dialogService.open(UpsertUserDialogComponent, {
data: {
action,
currentValue,
actions$: {
add: (user) => this.usersService.addUser({ user}),
edit: (user) => this.usersService.updateUser({ user }),
},
},
});
}
}

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































