-
Notifications
You must be signed in to change notification settings - Fork 26.6k
Closed
Labels
Milestone
Description
🐞 bug report
Affected Package
@angular/animation or @angular/platform-browser
Is this a regression?
No.
Description
The BrowserAnimationsModule and NoopAnimationsModule cause incomplete renders where there was none before.
🔬 Minimal Reproduction
https://stackblitz.com/edit/angular-after-view
When the button is toggled, the ngAfterViewChecked() shows that the DOM from both states are in the DOM simultaneously.
If you remove the NoopAnimationsModule altogether, there is only one state when ngAfterViewChecked() is run.
import { AfterViewChecked, ChangeDetectionStrategy, Component, ElementRef, Injectable, NgModule, VERSION } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class LogService {
private readonly _logs: string[] = [];
readonly logs = new BehaviorSubject<string[]>(this.logs);
clear() {
this._logs.length = 0;
this.logs.next(this._logs);
}
log(log: string) {
console.log(log);
this._logs.push(log);
this.logs.next(this._logs);
}
}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app',
template: `
<p class="block">Angular {{ version }}</p>
<container>
<button class="block" (click)="state = !state" type="button">Toggle content</button>
<div *ngIf="state" class="block state">On</div>
<div *ngIf="!state" class="block state">Off</div>
</container>
<log></log>
`,
})
export class AppComponent {
readonly version = VERSION.full;
state = false;
}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'container',
template: `
<ng-content></ng-content>
`,
})
export class ContainerComponent implements AfterViewChecked {
constructor(private readonly elementRef: ElementRef<HTMLElement>, private readonly logService: LogService) {}
ngAfterViewChecked() {
this.logService.log(`${this.elementRef.nativeElement.querySelectorAll('.state').length} states`);
}
}
@Component({
selector: 'log',
styles: [`
.log:not(:first-child) {
margin-top: 2px;
}
.log:not(:last-child) {
margin-bottom: 2px;
}
`],
template: `
<button class="block" (click)="logService.clear()" type="button">Clear logs</button>
<div class="block log" *ngFor="let log of logService.logs | async">{{ log }}</div>
`,
})
export class LogComponent {
constructor(readonly logService: LogService) {}
}
@NgModule({
declarations: [
AppComponent,
ContainerComponent,
LogComponent,
],
imports: [
BrowserModule,
NoopAnimationsModule,
],
bootstrap: [AppComponent],
providers: [
LogService,
],
})
export class AppModule { }
🌍 Your Environment
Angular Version:
7.1.4
Anything else relevant?
Because of this bug, there is no way (that I'm aware of) to reliably measure the DOM after updating the view but before browser render.