tengo un projecto en angular usando datatable-ajax y quiero que verifiques si sigo las buenas practicas de programacion especodifcamnete en como creo los botones - import {
AfterViewInit,
Component,
ElementRef,
OnDestroy,
OnInit,
Renderer2,
TemplateRef,
ViewChild,

} from ‘@angular/core’;
import { Config } from ‘datatables.net’;
import { Producto } from ‘…/…/models/producto.model’;
import { Subject } from ‘rxjs’;
import { ProductoService } from ‘…/services/producto.service’;
import Swal from ‘sweetalert2’;
import { Router } from ‘@angular/router’;
import { ADTSettings } from ‘angular-datatables/src/models/settings’;

@Component({
selector: ‘app-producto-listar’,
templateUrl: ‘./producto-listar.component.html’,
styleUrl: ‘./producto-listar.component.css’,
})
export class ProductoListarComponent
implements AfterViewInit, OnInit, OnDestroy
{
dtOptions: Config = {};
dtTrigger = new Subject<ADTSettings>();

@ViewChild(‘demoNg’, { static: true }) demoNg!: TemplateRef<any>;

constructor(
private productoService: ProductoService,
private router: Router,
private renderer: Renderer2, private el: ElementRef
) {}

ngOnInit(): void {
this.registerEvents();
}

ngAfterViewInit(): void {
const that = this;
this.dtOptions = {
ajax: (dataTablesParameters: any, callback) => {
this.listar(callback)
},

columns: [
{ title: ‘ID’, data: ‘idproducto’ },
{ title: ‘Fecha’, data: ‘fecha’ },
{ title: ‘Nombre’, data: ‘nombre’ },
{ title: ‘Precio Compra’, data: ‘preciocompra’ },
{ title: ‘Precio Venta’, data: ‘precioventa’ },
{ title: ‘Imagen’, data: ‘imagen’ },
{ title: ‘Activo’, data: ‘activo’ },
{ title: ‘Categoría’, data: ‘categoria.nombre’ },

{
title: ‘Acciones’,
data: null,
render: function (data, type, row) {
return &lt;button class="btn btn-warning btnActualizar me-1" data-id="{row.idproducto}"&gt;&lt;/button&gt;<br/> &lt;button class="btn btn-danger btnEliminar" data-id="{row.idproducto}" data-nombre="${row.nombre}"&gt;&lt;/button&gt;;
}
}


],
};

setTimeout(() => {
this.dtTrigger.next(this.dtOptions);
}, 200);


}

registerEvents(): void {
const that = this;
this.dtTrigger.subscribe(() => {
this.renderer.listen(‘document’, ‘click’, (event: Event) => {
const target = event.target as HTMLElement;
if (target.matches(‘.btnActualizar’)) {
const id = target.getAttribute(‘data-id’);
if (id) {
that.btnActualizar(parseInt(id, 10));
}
}
if (target.matches(‘.btnEliminar’)) {
const id = target.getAttribute(‘data-id’);
const nombre = target.getAttribute(‘data-nombre’)
if (id && nombre) {
that.mensajeConfirmacion(parseInt(id, 10), nombre);
}
}
});
});
}




btnActualizar(id: number) {
this.router.navigate([‘/producto/actualizar/’ + id]);
}

ngOnDestroy(): void {
this.dtTrigger?.unsubscribe();
}

refreshTable() {
const tabla = $(‘#tablaProducto’).DataTable();
tabla.ajax.reload();
}

listar(callback: any): void {
this.productoService.listarProductos().subscribe({
next: (productos: Producto[]) => {
callback({
data: productos,
});
},
error: (error) => {
console.error(‘Error al listar productos’, error);
}
});
}

mensajeConfirmacion(id: number, producto: string): void {
Swal.fire({
title: ‘¿Estás seguro?’,
icon: ‘warning’,
showCancelButton: true,
confirmButtonColor: ‘#28a745’,
cancelButtonColor: ‘#d33’,
confirmButtonText: ‘Si, ¡elimínalo!’,
cancelButtonText: ‘Cancelar’,
}).then((result) => {
if (result.isConfirmed) {
this.eliminar(id, producto);
}
});
}

mostrarNotificacion(
titulo: string,
texto: string,
icono: ‘success’ | ‘error’
): void {
Swal.fire({
title: titulo,
text: texto,
icon: icono,
});
}

eliminar(id: number, producto: string): void {
this.productoService.eliminarProducto(id).subscribe({
next: () => {
this.mostrarNotificacion(
‘Eliminado’,
'El producto ’ + producto + ‘ha sido eliminado’,
‘success’
);
this.refreshTable();
},
error: (error) => {
console.error(‘Error al eliminar producto’, error);
this.mostrarNotificacion(
‘Error’,
'Hubo un problema al eliminar el producto: ’ + producto,
‘error’
);
},
});
}
} - solo responde con texto en 5 lineas sin usar codigo