Skip to content

Commit

Permalink
fix(datagrid): do not run change detection when the input is focused …
Browse files Browse the repository at this point in the history
…asynchronously
  • Loading branch information
arturovt authored and mathisscott committed Mar 21, 2022
1 parent df4dda1 commit 24841a1
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 7 deletions.
2 changes: 1 addition & 1 deletion projects/angular/clarity.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4923,7 +4923,7 @@ export const CUSTOM_BUTTON_TYPES: any;
//
// @public (undocumented)
export class DatagridNumericFilter<T = any> extends DatagridFilterRegistrar<T, DatagridNumericFilterImpl<T>> implements CustomFilter, AfterViewInit {
constructor(filters: FiltersProvider<T>, domAdapter: DomAdapter, commonStrings: ClrCommonStringsService, popoverToggleService: ClrPopoverToggleService);
constructor(filters: FiltersProvider<T>, domAdapter: DomAdapter, commonStrings: ClrCommonStringsService, popoverToggleService: ClrPopoverToggleService, ngZone: NgZone);
// (undocumented)
commonStrings: ClrCommonStringsService;
set customNumericFilter(value: ClrDatagridNumericFilterInterface<T> | RegisteredFilter<T, DatagridNumericFilterImpl<T>>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ export default function (): void {
const input: HTMLInputElement = document.querySelector("input[type='number']");
spyOn(input, 'focus');
expect(input.focus).not.toHaveBeenCalled();
tick();
// The `requestAnimationFrame` is mocked through `setTimeout(fn, 16)`.
tick(16);
expect(input.focus).toHaveBeenCalled();
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, NgZone, Output, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';

import { ClrDatagridFilter } from '../../datagrid-filter';
Expand Down Expand Up @@ -52,7 +52,8 @@ export class DatagridNumericFilter<T = any>
filters: FiltersProvider<T>,
private domAdapter: DomAdapter,
public commonStrings: ClrCommonStringsService,
private popoverToggleService: ClrPopoverToggleService
private popoverToggleService: ClrPopoverToggleService,
private ngZone: NgZone
) {
super(filters);
}
Expand Down Expand Up @@ -104,9 +105,16 @@ export class DatagridNumericFilter<T = any>
this.subscriptions.push(
this.popoverToggleService.openChange.subscribe(openChange => {
this.open = openChange;
// The timeout in used because when this executes, the input isn't displayed.
setTimeout(() => {
this.domAdapter.focus(this.input.nativeElement);
// Note: this is being run outside of the Angular zone because `element.focus()` doesn't require
// running change detection.
this.ngZone.runOutsideAngular(() => {
// The animation frame in used because when this executes, the input isn't displayed.
// Note: `element.focus()` causes re-layout and this may lead to frame drop on slower devices.
// `setTimeout` is a macrotask and macrotasks are executed within the current rendering frame.
// Animation tasks are executed within the next rendering frame.
requestAnimationFrame(() => {
this.domAdapter.focus(this.input.nativeElement);
});
});
})
);
Expand Down

0 comments on commit 24841a1

Please sign in to comment.