Skip to content

Commit

Permalink
feat(material/list): return selected options from selection list sele…
Browse files Browse the repository at this point in the history
…ctAll/deselectAll (angular#21358)

Returns an array of the changed options from the list's `selectAll` and `deselectAll`.
This is information we have already so exposing it is trivial and makes some use
cases slightly easier.

Fixes angular#21356.
  • Loading branch information
crisbeto authored and wagnermaciel committed Feb 8, 2021
1 parent c3a97d6 commit c48fbea
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/material-experimental/mdc-list/selection-list.spec.ts
Expand Up @@ -418,10 +418,11 @@ describe('MDC-based MatSelectionList without forms', () => {

expect(list.options.toArray().every(option => option.selected)).toBe(false);

list.selectAll();
const result = list.selectAll();
fixture.detectChanges();

expect(list.options.toArray().every(option => option.selected)).toBe(true);
expect(result).toEqual(list.options.toArray());
});

it('should be able to select all options, even if they are disabled', () => {
Expand All @@ -444,10 +445,11 @@ describe('MDC-based MatSelectionList without forms', () => {
list.options.forEach(option => option.toggle());
expect(list.options.toArray().every(option => option.selected)).toBe(true);

list.deselectAll();
const result = list.deselectAll();
fixture.detectChanges();

expect(list.options.toArray().every(option => option.selected)).toBe(false);
expect(result).toEqual(list.options.toArray());
});

it('should be able to deselect all options, even if they are disabled', () => {
Expand Down
22 changes: 12 additions & 10 deletions src/material-experimental/mdc-list/selection-list.ts
Expand Up @@ -192,14 +192,14 @@ export class MatSelectionList extends MatInteractiveListBase<MatListOption>
this._element.nativeElement.focus(options);
}

/** Selects all of the options. */
selectAll() {
this._setAllOptionsSelected(true);
/** Selects all of the options. Returns the options that changed as a result. */
selectAll(): MatListOption[] {
return this._setAllOptionsSelected(true);
}

/** Deselects all of the options. */
deselectAll() {
this._setAllOptionsSelected(false);
/** Deselects all of the options. Returns the options that changed as a result. */
deselectAll(): MatListOption[] {
return this._setAllOptionsSelected(false);
}

/** Reports a value change to the ControlValueAccessor */
Expand Down Expand Up @@ -306,20 +306,22 @@ export class MatSelectionList extends MatInteractiveListBase<MatListOption>
* Sets the selected state on all of the options
* and emits an event if anything changed.
*/
private _setAllOptionsSelected(isSelected: boolean, skipDisabled?: boolean) {
private _setAllOptionsSelected(isSelected: boolean, skipDisabled?: boolean): MatListOption[] {
// Keep track of whether anything changed, because we only want to
// emit the changed event when something actually changed.
let hasChanged = false;
const changedOptions: MatListOption[] = [];

this.options.forEach(option => {
if ((!skipDisabled || !option.disabled) && option._setSelected(isSelected)) {
hasChanged = true;
changedOptions.push(option);
}
});

if (hasChanged) {
if (changedOptions.length) {
this._reportValueChange();
}

return changedOptions;
}

// Note: This getter exists for backwards compatibility. The `_items` query list
Expand Down
6 changes: 4 additions & 2 deletions src/material/list/selection-list.spec.ts
Expand Up @@ -655,10 +655,11 @@ describe('MatSelectionList without forms', () => {

expect(list.options.toArray().every(option => option.selected)).toBe(false);

list.selectAll();
const result = list.selectAll();
fixture.detectChanges();

expect(list.options.toArray().every(option => option.selected)).toBe(true);
expect(result).toEqual(list.options.toArray());
});

it('should be able to select all options, even if they are disabled', () => {
Expand All @@ -681,10 +682,11 @@ describe('MatSelectionList without forms', () => {
list.options.forEach(option => option.toggle());
expect(list.options.toArray().every(option => option.selected)).toBe(true);

list.deselectAll();
const result = list.deselectAll();
fixture.detectChanges();

expect(list.options.toArray().every(option => option.selected)).toBe(false);
expect(result).toEqual(list.options.toArray());
});

it('should be able to deselect all options, even if they are disabled', () => {
Expand Down
16 changes: 9 additions & 7 deletions src/material/list/selection-list.ts
Expand Up @@ -517,14 +517,14 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements CanD
this._element.nativeElement.focus(options);
}

/** Selects all of the options. */
selectAll() {
this._setAllOptionsSelected(true);
/** Selects all of the options. Returns the options that changed as a result. */
selectAll(): MatListOption[] {
return this._setAllOptionsSelected(true);
}

/** Deselects all of the options. */
deselectAll() {
this._setAllOptionsSelected(false);
/** Deselects all of the options. Returns the options that changed as a result. */
deselectAll(): MatListOption[] {
return this._setAllOptionsSelected(false);
}

/** Sets the focused option of the selection-list. */
Expand Down Expand Up @@ -672,7 +672,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements CanD
private _setAllOptionsSelected(
isSelected: boolean,
skipDisabled?: boolean,
isUserInput?: boolean) {
isUserInput?: boolean): MatListOption[] {
// Keep track of whether anything changed, because we only want to
// emit the changed event when something actually changed.
const changedOptions: MatListOption[] = [];
Expand All @@ -690,6 +690,8 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements CanD
this._emitChangeEvent(changedOptions);
}
}

return changedOptions;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions tools/public_api_guard/material/list.d.ts
Expand Up @@ -123,14 +123,14 @@ export declare class MatSelectionList extends _MatSelectionListMixinBase impleme
_removeOptionFromList(option: MatListOption): MatListOption | null;
_reportValueChange(): void;
_setFocusedOption(option: MatListOption): void;
deselectAll(): void;
deselectAll(): MatListOption[];
focus(options?: FocusOptions): void;
ngAfterContentInit(): void;
ngOnChanges(changes: SimpleChanges): void;
ngOnDestroy(): void;
registerOnChange(fn: (value: any) => void): void;
registerOnTouched(fn: () => void): void;
selectAll(): void;
selectAll(): MatListOption[];
setDisabledState(isDisabled: boolean): void;
writeValue(values: string[]): void;
static ngAcceptInputType_disableRipple: BooleanInput;
Expand Down

0 comments on commit c48fbea

Please sign in to comment.