Soy nuevo en Angular, trabajo con Angular 12 para una tarea escolar, intento crear una especie de ventana de chat que se actualice cada vez que el usuario envía un mensaje, pero no puedo encontrar una manera de hacer que se vuelva a procesar cuando agregar un nuevo objeto a la matriz.
chat.component.ts:
@Component({ selector: 'app-chat', templateUrl: './chat.component.html', styleUrls: ['./chat.component.scss'] }) @Injectable({ providedIn: 'root' }) export class ChatComponent implements OnInit { messageArray: Array<any>; constructor(private changeDetector: ChangeDetectorRef) { this.messageArray = [{message: "test message 1", style: "answer"}]; } ngOnInit(): void {} addMessage(message: string, style: string): void { this.messageArray = [...this.messageArray, {message: message, style: style}]; this.changeDetector.detectChanges(); console.log(this.messageArray); } }chat.componente.html:
<div class="container chatContainer"> <div class="row" *ngFor="let message of messageArray"> <div class="col"> <div class="text-wrap text-break message {{message.style}}"> {{message.message}} </div> </div> </div> </div>Intenté actualizar la matriz tanto con [...array] como con .push(), intenté usar [...array] para crear una nueva matriz después de presionar, probé tanto ChangeDetectionStrategy.Default como .OnPush, e intenté hacer todo esas cosas también en el componente principal que llama a mi método addMessage(). En todos los intentos, la matriz se registraría en la consola correctamente, pero se negaría a actualizar la vista.
¿Algunas ideas?
Si yo fuera tú, preferiría usar un BehaviorSubject y hacer algo como esto:
@Component({ selector: 'app-chat', templateUrl: './chat.component.html', styleUrls: ['./chat.component.scss'] }) @Injectable({ providedIn: 'root' }) export class ChatComponent implements OnInit { messageArray: BehaviorSubect<Array<any>>; constructor(private changeDetector: ChangeDetectorRef) { this.messageArray = new BehaviorSubject<Array<any>>([{message: "test message 1", style: "answer"}]); } ngOnInit(): void {} addMessage(message: string, style: string): void { this.messageArray.next([...this.messageArray, {message: message, style: style}]); } }chat.componente.html:
<div class="container chatContainer"> <div class="row" *ngFor="let message of messageArray | async"> <div class="col"> <div class="text-wrap text-break message {{message.style}}"> {{message.message}} </div> </div> </div> </div>Un colega me sugirió que usara @ViewChild para llamar al componente Chat en su lugar. Así que eliminé el @Injectable del chat como sugirió zer0, y cambié su componente de inicio principal a este:
export class HomeComponent implements OnInit { @ViewChild(ChatComponent) private chatComponent: any; constructor(private cdr: ChangeDetectorRef) { } ngOnInit(): void { } onSend(): void { this.chatComponent.addMessage("test message", "question"); this.cdr.detectChanges(); } }Funciona ahora. ¡Gracias!
Edito: una palabra