Skip to content

Commit f66486d

Browse files
committed
fix(material-experimental/mdc-slider): fix a few null pointer exceptions (#23659)
Fixes a few null pointer errors if: 1. `setDisabledState` is called too early. This can't happen at the moment, but it showed up when trying to fix something in `@angular/forms` and it may become an issue in the future. 2. The component is destroyed before the initialization is complete. This showed up while investigating the first error. (cherry picked from commit 1a03257)
1 parent edca54f commit f66486d

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

src/material-experimental/mdc-slider/slider.spec.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,13 @@ describe('MDC-based MatSlider', () => {
5252
}
5353

5454
describe('standard slider', () => {
55+
let fixture: ComponentFixture<StandardSlider>;
5556
let sliderInstance: MatSlider;
5657
let inputInstance: MatSliderThumb;
5758

5859
beforeEach(
5960
waitForAsync(() => {
60-
const fixture = createComponent(StandardSlider);
61+
fixture = createComponent(StandardSlider);
6162
fixture.detectChanges();
6263
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
6364
sliderInstance = sliderDebugElement.componentInstance;
@@ -104,6 +105,12 @@ describe('MDC-based MatSlider', () => {
104105
expect(inputInstance.value).toBe(10);
105106
sliderInstance._elementRef.nativeElement.style.marginLeft = 'initial';
106107
});
108+
109+
it('should not throw if destroyed before initialization is complete', () => {
110+
fixture.destroy();
111+
fixture = TestBed.createComponent(StandardSlider);
112+
expect(() => fixture.destroy()).not.toThrow();
113+
});
107114
});
108115

109116
describe('standard range slider', () => {

src/material-experimental/mdc-slider/slider.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -852,32 +852,32 @@ export class MatSlider
852852

853853
/** Sets the disabled state based on the disabled state of the inputs (ControlValueAccessor). */
854854
_updateDisabled(): void {
855-
const disabled = this._inputs.some(input => input._disabled);
855+
const disabled = this._inputs?.some(input => input._disabled) || false;
856856
this._setDisabled(disabled);
857857
}
858858

859859
/** Gets the slider thumb input of the given thumb position. */
860860
_getInput(thumbPosition: Thumb): MatSliderThumb {
861-
return thumbPosition === Thumb.END ? this._inputs.last! : this._inputs.first!;
861+
return thumbPosition === Thumb.END ? this._inputs?.last! : this._inputs?.first!;
862862
}
863863

864864
/** Gets the slider thumb HTML input element of the given thumb position. */
865865
_getInputElement(thumbPosition: Thumb): HTMLInputElement {
866-
return this._getInput(thumbPosition)._hostElement;
866+
return this._getInput(thumbPosition)?._hostElement;
867867
}
868868

869869
_getThumb(thumbPosition: Thumb): MatSliderVisualThumb {
870-
return thumbPosition === Thumb.END ? this._thumbs.last! : this._thumbs.first!;
870+
return thumbPosition === Thumb.END ? this._thumbs?.last! : this._thumbs?.first!;
871871
}
872872

873873
/** Gets the slider thumb HTML element of the given thumb position. */
874874
_getThumbElement(thumbPosition: Thumb): HTMLElement {
875-
return this._getThumb(thumbPosition)._getHostElement();
875+
return this._getThumb(thumbPosition)?._getHostElement();
876876
}
877877

878878
/** Gets the slider knob HTML element of the given thumb position. */
879879
_getKnobElement(thumbPosition: Thumb): HTMLElement {
880-
return this._getThumb(thumbPosition)._getKnob();
880+
return this._getThumb(thumbPosition)?._getKnob();
881881
}
882882

883883
/**
@@ -1167,7 +1167,7 @@ class SliderAdapter implements MDCSliderAdapter {
11671167
evtType: K,
11681168
handler: SpecificEventListener<K>,
11691169
): void => {
1170-
this._delegate._getThumbElement(thumbPosition).removeEventListener(evtType, handler);
1170+
this._delegate._getThumbElement(thumbPosition)?.removeEventListener(evtType, handler);
11711171
};
11721172
registerInputEventHandler = <K extends EventType>(
11731173
thumbPosition: Thumb,
@@ -1177,7 +1177,7 @@ class SliderAdapter implements MDCSliderAdapter {
11771177
if (evtType === 'change') {
11781178
this._saveChangeEventHandler(thumbPosition, handler as SpecificEventListener<EventType>);
11791179
} else {
1180-
this._delegate._getInputElement(thumbPosition).addEventListener(evtType, handler);
1180+
this._delegate._getInputElement(thumbPosition)?.addEventListener(evtType, handler);
11811181
}
11821182
};
11831183
deregisterInputEventHandler = <K extends EventType>(
@@ -1188,7 +1188,7 @@ class SliderAdapter implements MDCSliderAdapter {
11881188
if (evtType === 'change') {
11891189
this._globalEventSubscriptions.unsubscribe();
11901190
} else {
1191-
this._delegate._getInputElement(thumbPosition).removeEventListener(evtType, handler);
1191+
this._delegate._getInputElement(thumbPosition)?.removeEventListener(evtType, handler);
11921192
}
11931193
};
11941194
registerBodyEventHandler = <K extends EventType>(

0 commit comments

Comments
 (0)