Bunnynut
Bunnynut

Reputation: 1328

Angular 2 View doesnt update when input data changes

I have an Angular 2 application which contains a message feed that is an array of type IMessage. In the OnInit event the messages are retrieved from the server and displayed. So far so good. When i update the array of IMessage using this.messagea.unshift(newMessage); the view does not display the new message. When i loop through that same array I can see the new message is in the array and refreshing the page (and retrieve the new message from the database) also shows it.

My main component:

import { Component, OnInit } from '@angular/core'
import { IMessage } from './message.model';
import { MessageService } from './message.service';

@Component({
    selector: 'messages',
    template: `<message *ngFor="let message of messages" [message]="message"></message>`
})
export class MessagesComponent implements OnInit {
    private messages: IMessage[] = [];

    constructor(private messageService: MessageService) {

    }

    ngOnInit() {
        this.messageService.getMessages().subscribe((newMessages: IMessage[]) => {
            this.messages = newMessages;

            setTimeout(() => {
                let newMessage: IMessage = {
                    "id": 1,
                    "title": "TEST",
                    "message": "message"
                };
                this.messages.unshift(newMessage);
            });
        });

    }
}

I have read about change detection in Angular but using a ChangeDetectorRef and call its detectChanges() or markForCheck() functions do not update the feed with the new message.

I have noticed that when I output the messages directly instead of calling a child component the list is updated.

template: `<span *ngFor="let message of messages">{{message.title}}</span>`

Upvotes: 0

Views: 302

Answers (1)

bhavin jalodara
bhavin jalodara

Reputation: 1530

when calling messageService.getMessages() your code might be running outside the angular. that is why when you assign values to variable it doesn't update the view.

try running code inside the angular NgZone. after that your view will be updated successfully.

import { Component, OnInit } from '@angular/core'
import { IMessage } from './message.model';
import { MessageService } from './message.service';
import {
    NgZone,
    ChangeDetectorRef
} from "@angular/core";
@Component({
    selector: 'messages',
    template: `<message *ngFor="let message of messages" [message]="message"></message>`
})
export class MessagesComponent implements OnInit {
    private messages: IMessage[] = [];

    constructor(private messageService: MessageService,private zone:NgZone) {

    }

    ngOnInit() {
        this.messageService.getMessages().subscribe((newMessages: IMessage[]) => {
            this.zone.run(()=>{
                this.messages = newMessages;
            });


            setTimeout(() => {
                let newMessage: IMessage = {
                    "id": 1,
                    "title": "TEST",
                    "message": "message"
                };
                this.zone.run(()=>{
                    this.messages.unshift(newMessage);
                });
            });
        });
    }
}

Upvotes: 1

Related Questions