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.
  • Loading branch information
crisbeto authored Mar 8, 2022
1 parent cfd8908 commit 1a03257
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 @@ -46,12 +46,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 @@ -98,6 +99,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 1a03257

Please sign in to comment.