I've been working on a simple auto-scroll directive for chat-display:
@Directive({
selector: "[autoScroll]"
})
export class AutoScroll {
@Input() inScrollHeight;
@Input() inClientHeight;
@HostBinding("scrollTop") outScrollTop;
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
if (changes["inScrollHeight"] || changes["inClientHeight"]) {
this.scroll();
}
};
scroll() {
this.outScrollTop = this.inScrollHeight - this.inClientHeight;
};
}
This directive will work when I've set enableProdMode()
and when the ChangeDetectionStrategy
is set to default, but when in "dev mode" I get an exception. I can set the ChangeDetectionStrategy
to onPush
, in that case the exception doesn't occur but the scroll will lag behind.
Is there a way to better structure this code so that Dom will be updated then the Scroll function can be called? I've tried setTimeout()
but that makes the delay worse, tried using ChangeDetectorRef
and subscribing to the observable to trigger markForCheck()
. Using ngAfterViewChecked()
causes browser crashes.
@Component({
selector: "chat-display",
template: `
<div class="chat-box" #this [inScrollHeight]="this.scrollHeight" [inClientHeight]="this.clientHeight" autoScroll>
<p *ngFor="#msg of messages | async | messageFilter:username:inSelectedTarget:inTargetFilter:inDirectionFilter" [ngClass]="msg.type">{{msg.message}}</p>
</div>
`,
styles: [`.whisper {
color: rosybrown;
}`],
directives: [NgClass, AutoScroll],
pipes: [AsyncPipe, MessageFilterPipe],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChatDisplay implements OnInit {
username: string;
@Input() inSelectedTarget: string;
@Input() inTargetFilter: boolean;
@Input() inDirectionFilter: boolean;
messages: Observable<ChatType[]>;
constructor(private socketService_: SocketService, private authService_: AuthService) {
this.username = this.authService_.username;
};
ngOnInit() {
}
}
This is the the exception that is triggered when in dev mode:
EXCEPTION: Expression 'this.scrollHeight in ChatDisplay@1:40' has changed after it was checked. Previous value: '417'. Current value: '420' in [this.scrollHeight in ChatDisplay@1:40] angular2.dev.js (23083,9)
scroll
event? What is callingscroll()
? – PaderewskidevMode
as well. Only working inprodMode
is smelly. – Paderewski