angular - Cómo agregar elementos a la página en tiempo de ejecución
Estoy creando una aplicación web de demostración en Angular para la universidad y quiero hacer clic en un button para agregar un nuevo nodo al árbol DOM. En JavaScript, usaría
document.getElementById('ticket-container').appendChild('app-ticket');
No parece que pueda encontrar una respuesta a esto y hubiera pensado que sería sencillo.
¿Cuál es la mejor manera de hacer esto en Angular 8?
*ngFor="let ticket of ticketcount; index as i;
Aquí está mi archivo ts del componente padre:
import { Component, OnInit } from '@angular/core';
class Ticket {
name: string;
price: number;
constructor(x: string, y: number){
this.name = x;
this.price = y;
}
}
@Component({
selector: 'app-purchase-tickets',
templateUrl: './purchase-tickets.component.html',
styleUrls: ['./purchase-tickets.component.scss']
})
export class PurchaseTicketsComponent implements OnInit {
total: number;
ticketCount: number;
constructor() {
}
ngOnInit() {
this.total = 0;
this.ticketCount = 0;
}
incrementTotal() {
this.total += 5;
this.ticketCount ++;
this.renderNewTicket();
}
renderNewTicket() {
//render ticket code here
}
}
y el archivo de plantilla es:
<main id='ticket-container'>
<app-ticket ></app-ticket>
<button mat-icon-button aria-label="new ticket" id="add-ticket" (click)="incrementTotal()" >
<mat-icon>add</mat-icon>
</button>
</main>
<p>Total: €{{total}}</p>
Respuesta #1
Como mencioné en mis comentarios, parece que necesitas usar un arreglo para almacenar los elementos y luego listarlos en la interfaz de usuario usando un *ngFor
Aquí, prueba esto:
import { Component } from "@angular/core";
interface Ticket {
name: string;
price: number;
}
@Component({
selector: "grid-list-overview-example",
styleUrls: ["grid-list-overview-example.css"],
templateUrl: "grid-list-overview-example.html"
})
export class GridListOverviewExample {
tickets: Array<Ticket> = [];
total: number;
ngOnInit() {
this.addTicket();
}
addTicket() {
this.tickets.push({
name: `Ticket ${this.tickets.length + 1}`,
price: 10
});
this.calculateTotal();
}
calculateTotal() {
this.total = this.tickets
.map(ticket => ticket.price)
.reduce((a, b) => a + b, 0);
}
}
Y en tu plantilla:
<main id='ticket-container'>
<mat-grid-list cols="2" rowHeight="2:1">
<mat-grid-tile *ngFor="let ticket of tickets">{{ ticket.name }}</mat-grid-tile>
</mat-grid-list>
<button mat-icon-button aria-label="new ticket" id="add-ticket" (click)="addTicket()" >
<mat-icon>add</mat-icon>
</button>
<p>Total: €{{total}}</p>
</main>
Aquí hay un ejemplo funcional en StackBlitz para tu referencia.
Respuesta #2
Estás usando *ngfor, así que almacena los valores relacionados con el ticket en un arreglo (arreglo de objetos ticket) y úsalo en la plantilla (con *ngfor). ticketCount es un número y *ngfor espera un arreglo. Agrega un método en el archivo TS para manejar el evento de clic del botón y en ese método agrega un nuevo valor a ese arreglo. La interfaz de usuario se actualiza en consecuencia.
