Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(material/list): return selected options from selection list selectAll/deselectAll #21358

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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