0

Hello I have component for chat messages. I have a problem with change detection. When I typed, ngFor directive still redraws all messages. I would like to draw messages when I displayed this component and then after I added new message. Here is my code:

chat.component.ts:

@Component({
    selector: 'my-chat',
    templateUrl: './chat.component.html',
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChatComponent implements OnInit {
    text: string;
    @Input() messages: ChatMessage[];
    @Output() onChanged: EventEmitter<string> = new EventEmitter<string>();
    constructor(private app: App, private cd: ChangeDetectorRef) {}

    ngOnInit() {
        this.messages = !this.messages ? [] : this.messages;        
    }

    onChangeHandler(value: string) {
        this.onChanged.emit(value);
    }

    trackByFn(index, item){
        console.log(index, item); //still calls when typing
        return item.Id;
    }
}

export interface ChatMessage {
    Text: string;
}

chat.component.html:

<form action="#" method="post" *ngIf="!readonly" [style.margin-bottom]="'10px'">
    <div class="img-push" [ngClass]="{'input-group': enableSaveButton}">
        <textarea class="form-control input-sm" rows="2" style="resize:none" [(ngModel)]="text" [ngModelOptions]="{standalone: true}"
         (ngModelChange)="onChangeHandler($event)"></textarea>
    </div>
</form>
<div class="box-body box-comments pre-scrollable">
    <ng-container *ngIf="messages.length != 0">
        <div class="box-comment" *ngFor="let message of messages; let i=index;trackBy:trackByFn">
            <div class="comment-text">
                <pre>{{message.Text}}</pre>
            </div>
        </div>
    </ng-container>
</div>
6
  • Which Angular version do you use? I know you have written 2 in the title but people still sometimes refer to newer versions of Angular as Angular 2. Commented Mar 26, 2018 at 5:26
  • What is the condition which decides if this component is to be displayed? Commented Mar 26, 2018 at 5:42
  • @DanMacák I have angular in version 4.0.0 Commented Mar 26, 2018 at 5:46
  • @Abhi <my-chat [messages]="data.Messages" (onChanged)="hasChanges($event)" *ngIf="data.Messages"/> Commented Mar 26, 2018 at 5:49
  • Check data.Messages variable. *ngIf="data.Messages" is probably making your component visible even if it is []. You probably want to formulate a different condition to make your component visible. If you want to not display this component until user actually enters a new message, then you will have to compare the lengths of the message array. Basically, you have to make your component visible at accurate event. Commented Mar 26, 2018 at 5:54

1 Answer 1

1

I tried exactly your code snippet and found out that the elements under the rule of *ngFor are not being rerendered. The trackByFn function is still being called while changing the text, but only as a part of ngDoCheck call in NgForOf directive, which is a directive that gets automatically created when you use *ngFor.

You can verify that in Chrome in devtools in the DOM inspector. If the elements are being rerendered, you see roughly the same as here enter image description here (taken from this article)

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.