Skip to content

Commit

Permalink
fix(material-experimental/mdc-slider): fix a few null pointer excepti…
Browse files Browse the repository at this point in the history
…ons (#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)
  • Loading branch information
crisbeto committed Mar 8, 2022
1 parent edca54f commit f66486d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
9 changes: 8 additions & 1 deletion src/material-experimental/mdc-slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,13 @@ describe('MDC-based MatSlider', () => {
}

describe('standard slider', () => {
let fixture: ComponentFixture<StandardSlider>;
let sliderInstance: MatSlider;
let inputInstance: MatSliderThumb;

beforeEach(
waitForAsync(() => {
const fixture = createComponent(StandardSlider);
fixture = createComponent(StandardSlider);
fixture.detectChanges();
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
sliderInstance = sliderDebugElement.componentInstance;
Expand Down Expand Up @@ -104,6 +105,12 @@ describe('MDC-based MatSlider', () => {
expect(inputInstance.value).toBe(10);
sliderInstance._elementRef.nativeElement.style.marginLeft = 'initial';
});

it('should not throw if destroyed before initialization is complete', () => {
fixture.destroy();
fixture = TestBed.createComponent(StandardSlider);
expect(() => fixture.destroy()).not.toThrow();
});
});

describe('standard range slider', () => {
Expand Down
18 changes: 9 additions & 9 deletions src/material-experimental/mdc-slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -852,32 +852,32 @@ export class MatSlider

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

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

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

_getThumb(thumbPosition: Thumb): MatSliderVisualThumb {
return thumbPosition === Thumb.END ? this._thumbs.last! : this._thumbs.first!;
return thumbPosition === Thumb.END ? this._thumbs?.last! : this._thumbs?.first!;
}

/** Gets the slider thumb HTML element of the given thumb position. */
_getThumbElement(thumbPosition: Thumb): HTMLElement {
return this._getThumb(thumbPosition)._getHostElement();
return this._getThumb(thumbPosition)?._getHostElement();
}

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

/**
Expand Down Expand Up @@ -1167,7 +1167,7 @@ class SliderAdapter implements MDCSliderAdapter {
evtType: K,
handler: SpecificEventListener<K>,
): void => {
this._delegate._getThumbElement(thumbPosition).removeEventListener(evtType, handler);
this._delegate._getThumbElement(thumbPosition)?.removeEventListener(evtType, handler);
};
registerInputEventHandler = <K extends EventType>(
thumbPosition: Thumb,
Expand All @@ -1177,7 +1177,7 @@ class SliderAdapter implements MDCSliderAdapter {
if (evtType === 'change') {
this._saveChangeEventHandler(thumbPosition, handler as SpecificEventListener<EventType>);
} else {
this._delegate._getInputElement(thumbPosition).addEventListener(evtType, handler);
this._delegate._getInputElement(thumbPosition)?.addEventListener(evtType, handler);
}
};
deregisterInputEventHandler = <K extends EventType>(
Expand All @@ -1188,7 +1188,7 @@ class SliderAdapter implements MDCSliderAdapter {
if (evtType === 'change') {
this._globalEventSubscriptions.unsubscribe();
} else {
this._delegate._getInputElement(thumbPosition).removeEventListener(evtType, handler);
this._delegate._getInputElement(thumbPosition)?.removeEventListener(evtType, handler);
}
};
registerBodyEventHandler = <K extends EventType>(
Expand Down

0 comments on commit f66486d

Please sign in to comment.