Implementación de cuadros de diálogo Upsert Form en Angular
Muchas aplicaciones requieren la capacidad de crear y actualizar registros a través de la interfaz de usuario. Por lo general, querremos utilizar el mismo componente de diálogo para ambas operaciones. El término "upsert" es una combinación de las palabras "update" e "insert", y se refiere al hecho de que el cuadro de diálogo se puede usar para crear un nuevo registro o actualizar uno existente.
Veamos cómo podemos implementar esta funcionalidad. Usaré la ngneat/dialogbiblioteca, pero tú puedes usar lo que prefieras. Primero, crearemos una interfaz compartida para lo dataque necesitamos pasar a nuestro diálogo:
export interface UpsertDialogData<T> {
action: 'add' | 'edit';
actions$: Record<
UpsertDialogData['type'],
(value: T) => Observable<any>
>;
currentValue: T | undefined;
}
Ahora vamos a crear el upsertcomponente de diálogo base:
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]);
});
}
}
Usemos nuestra clase base y creemos un diálogo para alterar a un usuario:
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 }),
},
},
});
}
}

![¿Qué es una lista vinculada, de todos modos? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































