Skip to content

Commit 681314e

Browse files
crisbetojelbourn
authored andcommitted
refactor: use strongly-typed ElementRef (#10825)
Currently the `nativeElement` in all of the `ElementRef` usages is typed to be `any`. These changes add proper typing to help us catch some errors at compile time.
1 parent 8956d1d commit 681314e

File tree

68 files changed

+143
-128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+143
-128
lines changed

guides/creating-a-custom-form-field-control.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,31 +159,31 @@ private _placeholder: string;
159159

160160
#### `ngControl`
161161

162-
This property allows the form field control to specify the `@angular/forms` control that is bound to this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll just set this to `null` in our component.
162+
This property allows the form field control to specify the `@angular/forms` control that is bound to this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll just set this to `null` in our component.
163163

164164
```ts
165165
ngControl: NgControl = null;
166166
```
167167

168-
It is likely you will want to implement `ControlValueAccessor` so that your component can work with `formControl` and `ngModel`. If you do implement `ControlValueAccessor` you will need to get a reference to the `NgControl` associated with your control and make it publicly available.
168+
It is likely you will want to implement `ControlValueAccessor` so that your component can work with `formControl` and `ngModel`. If you do implement `ControlValueAccessor` you will need to get a reference to the `NgControl` associated with your control and make it publicly available.
169169

170170
The easy way is to add it as a public property to your constructor and let dependency injection handle it:
171171

172172
```ts
173173
constructor(
174-
...,
174+
...,
175175
@Optional() @Self() public ngControl: NgControl,
176176
...,
177177
) { }
178178
```
179179

180-
Note that if your component implements `ControlValueAccessor`, it may already be set up to provide `NG_VALUE_ACCESSOR` (in the `providers` part of the component's decorator, or possibly in a module declaration). If so you may get a *cannot instantiate cyclic dependency* error.
180+
Note that if your component implements `ControlValueAccessor`, it may already be set up to provide `NG_VALUE_ACCESSOR` (in the `providers` part of the component's decorator, or possibly in a module declaration). If so you may get a *cannot instantiate cyclic dependency* error.
181181

182182
To resolve this, remove the `NG_VALUE_ACCESSOR` provider and instead set the value accessor directly:
183183

184184
```ts
185185
constructor(
186-
...,
186+
...,
187187
@Optional() @Self() public ngControl: NgControl,
188188
...,
189189
) {
@@ -207,7 +207,7 @@ need to remember to emit on the `stateChanges` stream so change detection can ha
207207
```ts
208208
focused = false;
209209

210-
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef) {
210+
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>) {
211211
...
212212
fm.monitor(elRef.nativeElement, true).subscribe(origin => {
213213
this.focused = !!origin;

src/cdk-experimental/dialog/dialog-container.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
104104
_afterExit: Subject<void> = new Subject();
105105

106106
constructor(
107-
private _elementRef: ElementRef,
107+
private _elementRef: ElementRef<HTMLElement>,
108108
private _focusTrapFactory: FocusTrapFactory,
109109
private _changeDetectorRef: ChangeDetectorRef,
110110
@Optional() @Inject(DOCUMENT) private _document: any,

src/cdk/a11y/aria-describer/aria-describer.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,16 @@ function expectMessage(el: Element, message: string) {
181181
`,
182182
})
183183
class TestApp {
184-
@ViewChild('element1') _element1: ElementRef;
184+
@ViewChild('element1') _element1: ElementRef<HTMLElement>;
185185
get element1(): Element { return this._element1.nativeElement; }
186186

187-
@ViewChild('element2') _element2: ElementRef;
187+
@ViewChild('element2') _element2: ElementRef<HTMLElement>;
188188
get element2(): Element { return this._element2.nativeElement; }
189189

190-
@ViewChild('element3') _element3: ElementRef;
190+
@ViewChild('element3') _element3: ElementRef<HTMLElement>;
191191
get element3(): Element { return this._element3.nativeElement; }
192192

193-
@ViewChild('element4') _element4: ElementRef;
193+
@ViewChild('element4') _element4: ElementRef<HTMLElement>;
194194
get element4(): Element { return this._element4.nativeElement; }
195195

196196

src/cdk/a11y/focus-monitor/focus-monitor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export class CdkMonitorFocus implements OnDestroy {
389389
private _monitorSubscription: Subscription;
390390
@Output() cdkFocusChange = new EventEmitter<FocusOrigin>();
391391

392-
constructor(private _elementRef: ElementRef, private _focusMonitor: FocusMonitor) {
392+
constructor(private _elementRef: ElementRef<HTMLElement>, private _focusMonitor: FocusMonitor) {
393393
this._monitorSubscription = this._focusMonitor.monitor(
394394
this._elementRef.nativeElement,
395395
this._elementRef.nativeElement.hasAttribute('cdkMonitorSubtreeFocus'))

src/cdk/a11y/focus-trap/focus-trap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ export class CdkTrapFocus implements OnDestroy, AfterContentInit, DoCheck {
350350
private _autoCapture: boolean;
351351

352352
constructor(
353-
private _elementRef: ElementRef,
353+
private _elementRef: ElementRef<HTMLElement>,
354354
private _focusTrapFactory: FocusTrapFactory,
355355
@Inject(DOCUMENT) _document: any) {
356356

src/cdk/observers/observe-content.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ export class CdkObserveContent implements AfterContentInit, OnDestroy {
164164

165165
private _currentSubscription: Subscription | null = null;
166166

167-
constructor(private _contentObserver: ContentObserver, private _elementRef: ElementRef,
167+
constructor(private _contentObserver: ContentObserver,
168+
private _elementRef: ElementRef<HTMLElement>,
168169
private _ngZone: NgZone) {}
169170

170171
ngAfterContentInit() {

src/cdk/overlay/position/connected-position-strategy.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ describe('ConnectedPositionStrategy', () => {
6363

6464
let originElement: HTMLElement;
6565
let positionStrategy: ConnectedPositionStrategy;
66-
let fakeElementRef: ElementRef;
66+
let fakeElementRef: ElementRef<HTMLElement>;
6767

6868
let originRect: ClientRect | null;
6969
let originCenterX: number | null;
@@ -73,7 +73,7 @@ describe('ConnectedPositionStrategy', () => {
7373
// The origin and overlay elements need to be in the document body in order to have geometry.
7474
originElement = createPositionedBlockElement();
7575
document.body.appendChild(originElement);
76-
fakeElementRef = new ElementRef(originElement);
76+
fakeElementRef = new ElementRef<HTMLElement>(originElement);
7777
});
7878

7979
afterEach(() => {
@@ -583,7 +583,7 @@ describe('ConnectedPositionStrategy', () => {
583583
let positionChangeHandler: jasmine.Spy;
584584
let onPositionChangeSubscription: Subscription;
585585
let positionChange: ConnectedOverlayPositionChange;
586-
let fakeElementRef: ElementRef;
586+
let fakeElementRef: ElementRef<HTMLElement>;
587587
let positionStrategy: ConnectedPositionStrategy;
588588

589589
beforeEach(() => {
@@ -597,14 +597,14 @@ describe('ConnectedPositionStrategy', () => {
597597
scrollable.appendChild(originElement);
598598

599599
// Create a strategy with knowledge of the scrollable container
600-
fakeElementRef = new ElementRef(originElement);
600+
fakeElementRef = new ElementRef<HTMLElement>(originElement);
601601
positionStrategy = overlay.position().connectedTo(
602602
fakeElementRef,
603603
{originX: 'start', originY: 'bottom'},
604604
{overlayX: 'start', overlayY: 'top'});
605605

606606
positionStrategy.withScrollableContainers([
607-
new CdkScrollable(new ElementRef(scrollable), null!, null!)]);
607+
new CdkScrollable(new ElementRef<HTMLElement>(scrollable), null!, null!)]);
608608
positionChangeHandler = jasmine.createSpy('positionChangeHandler');
609609
onPositionChangeSubscription =
610610
positionStrategy.onPositionChange.subscribe(positionChangeHandler);
@@ -673,13 +673,13 @@ describe('ConnectedPositionStrategy', () => {
673673
describe('positioning properties', () => {
674674
let originElement: HTMLElement;
675675
let positionStrategy: ConnectedPositionStrategy;
676-
let fakeElementRef: ElementRef;
676+
let fakeElementRef: ElementRef<HTMLElement>;
677677

678678
beforeEach(() => {
679679
// The origin and overlay elements need to be in the document body in order to have geometry.
680680
originElement = createPositionedBlockElement();
681681
document.body.appendChild(originElement);
682-
fakeElementRef = new ElementRef(originElement);
682+
fakeElementRef = new ElementRef<HTMLElement>(originElement);
683683
});
684684

685685
afterEach(() => {

src/cdk/overlay/position/connected-position-strategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
5858
constructor(
5959
originPos: OriginConnectionPosition,
6060
overlayPos: OverlayConnectionPosition,
61-
connectedTo: ElementRef,
61+
connectedTo: ElementRef<HTMLElement>,
6262
viewportRuler: ViewportRuler,
6363
document: Document,
6464
// @breaking-change 7.0.0 `platform` parameter to be made required.

src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
15751575
}]);
15761576

15771577
strategy.withScrollableContainers([
1578-
new CdkScrollable(new ElementRef(scrollable), null!, null!)
1578+
new CdkScrollable(new ElementRef<HTMLElement>(scrollable), null!, null!)
15791579
]);
15801580

15811581
positionChangeHandler = jasmine.createSpy('positionChange handler');

src/cdk/scrolling/scroll-dispatcher.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe('ScrollDispatcher', () => {
117117
describe('Nested scrollables', () => {
118118
let scroll: ScrollDispatcher;
119119
let fixture: ComponentFixture<NestedScrollingComponent>;
120-
let element: ElementRef;
120+
let element: ElementRef<HTMLElement>;
121121

122122
beforeEach(inject([ScrollDispatcher], (s: ScrollDispatcher) => {
123123
scroll = s;
@@ -228,7 +228,7 @@ describe('ScrollDispatcher', () => {
228228
})
229229
class ScrollingComponent {
230230
@ViewChild(CdkScrollable) scrollable: CdkScrollable;
231-
@ViewChild('scrollingElement') scrollingElement: ElementRef;
231+
@ViewChild('scrollingElement') scrollingElement: ElementRef<HTMLElement>;
232232
}
233233

234234

@@ -245,7 +245,7 @@ class ScrollingComponent {
245245
`
246246
})
247247
class NestedScrollingComponent {
248-
@ViewChild('interestingElement') interestingElement: ElementRef;
248+
@ViewChild('interestingElement') interestingElement: ElementRef<HTMLElement>;
249249
}
250250

251251
const TEST_COMPONENTS = [ScrollingComponent, NestedScrollingComponent];

0 commit comments

Comments
 (0)