refactor: add utility for coercing element refs (#14258)

Since we're having more and more APIs that accept both an `ElementRef` and an `Element`, we have a few places that repeat the same logic for coercing the value to an `Element`. These changes add a utility function that can be used everywhere.
This commit is contained in:
Kristiyan Kostadinov
2018-12-19 16:13:28 +01:00
committed by Jeremy Elbourn
parent e673608476
commit 2463200324
10 changed files with 52 additions and 17 deletions
+4 -7
View File
@@ -19,6 +19,7 @@ import {
SkipSelf,
} from '@angular/core';
import {Observable, of as observableOf, Subject, Subscription} from 'rxjs';
import {coerceElement} from '@angular/cdk/coercion';
// This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
@@ -158,7 +159,7 @@ export class FocusMonitor implements OnDestroy {
return observableOf(null);
}
const nativeElement = this._getNativeElement(element);
const nativeElement = coerceElement(element);
// Check if we're already monitoring this element.
if (this._elementInfo.has(nativeElement)) {
@@ -206,7 +207,7 @@ export class FocusMonitor implements OnDestroy {
stopMonitoring(element: ElementRef<HTMLElement>): void;
stopMonitoring(element: HTMLElement | ElementRef<HTMLElement>): void {
const nativeElement = this._getNativeElement(element);
const nativeElement = coerceElement(element);
const elementInfo = this._elementInfo.get(nativeElement);
if (elementInfo) {
@@ -239,7 +240,7 @@ export class FocusMonitor implements OnDestroy {
origin: FocusOrigin,
options?: FocusOptions): void {
const nativeElement = this._getNativeElement(element);
const nativeElement = coerceElement(element);
this._setOriginForCurrentEventQueue(origin);
@@ -418,10 +419,6 @@ export class FocusMonitor implements OnDestroy {
clearTimeout(this._originTimeoutId);
}
}
private _getNativeElement(element: HTMLElement | ElementRef<HTMLElement>): HTMLElement {
return element instanceof ElementRef ? element.nativeElement : element;
}
}
+6 -2
View File
@@ -1,24 +1,28 @@
package(default_visibility=["//visibility:public"])
load("//tools:defaults.bzl", "ts_library", "jasmine_node_test", "markdown_to_html")
load("//tools:defaults.bzl", "ts_library", "ts_web_test_suite", "markdown_to_html")
ts_library(
name = "coercion",
srcs = glob(["**/*.ts"], exclude=["**/*.spec.ts"]),
module_name = "@angular/cdk/coercion",
deps = [
"@angular//packages/core",
]
)
ts_library(
name = "coercion_test_sources",
srcs = glob(["**/*.spec.ts"]),
deps = [
"@angular//packages/core",
"@matdeps//@types/jasmine",
":coercion"
],
testonly = 1,
)
jasmine_node_test(
ts_web_test_suite(
name = "unit_tests",
deps = [":coercion_test_sources"],
)
+13
View File
@@ -0,0 +1,13 @@
import {ElementRef} from '@angular/core';
import {coerceElement} from './element';
describe('coerceElement', () => {
it('should coerce an ElementRef into an element', () => {
const ref = new ElementRef(document.body);
expect(coerceElement(ref)).toBe(document.body);
});
it('should return the element, if a native element is passed in', () => {
expect(coerceElement(document.body)).toBe(document.body);
});
});
+17
View File
@@ -0,0 +1,17 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ElementRef} from '@angular/core';
/**
* Coerces an ElementRef or an Element into an element.
* Useful for APIs that can accept either a ref or the native element itself.
*/
export function coerceElement<T>(elementOrRef: ElementRef<T> | T): T {
return elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
}
+1
View File
@@ -10,3 +10,4 @@ export * from './boolean-property';
export * from './number-property';
export * from './array';
export * from './css-pixel-value';
export * from './element';
+2 -2
View File
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
import {coerceBooleanProperty, coerceNumberProperty, coerceElement} from '@angular/cdk/coercion';
import {
AfterContentInit,
Directive,
@@ -63,7 +63,7 @@ export class ContentObserver implements OnDestroy {
observe(element: ElementRef<Element>): Observable<MutationRecord[]>;
observe(elementOrRef: Element | ElementRef<Element>): Observable<MutationRecord[]> {
const element = elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
const element = coerceElement(elementOrRef);
return Observable.create((observer: Observer<MutationRecord[]>) => {
const stream = this._observeElement(element);
@@ -19,7 +19,7 @@ import {
import {Observable, Subscription, Subject, Observer} from 'rxjs';
import {OverlayReference} from '../overlay-reference';
import {isElementScrolledOutsideView, isElementClippedByScrolling} from './scroll-clip';
import {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';
import {coerceCssPixelValue, coerceArray, coerceElement} from '@angular/cdk/coercion';
import {Platform} from '@angular/cdk/platform';
import {OverlayContainer} from '../overlay-container';
@@ -431,7 +431,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
* @param origin Reference to the new origin element.
*/
setOrigin(origin: ElementRef | HTMLElement): this {
this._origin = origin instanceof ElementRef ? origin.nativeElement : origin;
this._origin = coerceElement(origin);
return this;
}
+3 -2
View File
@@ -17,6 +17,7 @@ import {
OnInit,
Output,
} from '@angular/core';
import {coerceElement} from '@angular/cdk/coercion';
import {EMPTY, Observable, Subject} from 'rxjs';
@@ -70,7 +71,7 @@ export class AutofillMonitor implements OnDestroy {
return EMPTY;
}
const element = elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
const element = coerceElement(elementOrRef);
const info = this._monitoredElements.get(element);
if (info) {
@@ -122,7 +123,7 @@ export class AutofillMonitor implements OnDestroy {
stopMonitoring(element: ElementRef<Element>): void;
stopMonitoring(elementOrRef: Element | ElementRef<Element>): void {
const element = elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
const element = coerceElement(elementOrRef);
const info = this._monitoredElements.get(element);
if (info) {
+2 -2
View File
@@ -70,10 +70,10 @@ export declare class FocusKeyManager<T> extends ListKeyManager<FocusableOption &
export declare class FocusMonitor implements OnDestroy {
constructor(_ngZone: NgZone, _platform: Platform);
_onBlur(event: FocusEvent, element: HTMLElement): void;
focusVia(element: ElementRef<HTMLElement>, origin: FocusOrigin, options?: FocusOptions): void;
focusVia(element: HTMLElement, origin: FocusOrigin, options?: FocusOptions): void;
monitor(element: HTMLElement, checkChildren?: boolean): Observable<FocusOrigin>;
focusVia(element: ElementRef<HTMLElement>, origin: FocusOrigin, options?: FocusOptions): void;
monitor(element: ElementRef<HTMLElement>, checkChildren?: boolean): Observable<FocusOrigin>;
monitor(element: HTMLElement, checkChildren?: boolean): Observable<FocusOrigin>;
ngOnDestroy(): void;
stopMonitoring(element: ElementRef<HTMLElement>): void;
stopMonitoring(element: HTMLElement): void;
+2
View File
@@ -6,5 +6,7 @@ export declare function coerceBooleanProperty(value: any): boolean;
export declare function coerceCssPixelValue(value: any): string;
export declare function coerceElement<T>(elementOrRef: ElementRef<T> | T): T;
export declare function coerceNumberProperty(value: any): number;
export declare function coerceNumberProperty<D>(value: any, fallback: D): number | D;