0

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>`
5
  • The problem is that // call to service to retrieve message, returns the response after your setTimeout(...)` was already executed. Your approach is entirely invalid. Please post the actual code of // call to service ... so that it's possible to make suggestions how to fix it (or check the docs at angular.io). Commented Jul 20, 2017 at 12:17
  • Your component has itself in the template. Are you sure you understand what you are doing? Commented Jul 20, 2017 at 12:23
  • @Damask that was a typo, fixed that Commented Jul 20, 2017 at 12:25
  • There is no messages property in you component but you manage to iterate over it. Commented Jul 20, 2017 at 12:28
  • Agree with Gunter - no need for setTimeout here. Read: auth0.com/blog/understanding-angular-2-change-detection Commented Aug 19, 2017 at 4:36

1 Answer 1

1

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);
                });
            });
        });
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.