mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(selection-list): support specifying theme color (#15237)
Currently the selection list always uses the `accent` color for the underlying pseudo checkbox of list options. In order to make this configurable by the user, we add a `color` input that matches our other usages of the `color` input in order to be consistent. Since we want to allow that a color can be specified for the `<mat-selection-list>` and that it's possible to overwrite the color for an individual list option, we don't use the color mixin as it brings in a lot of overhead and also doesn't make it easy to provide the desired precedence for individual options. Also we **can't** set the color class on the `<mat-selection-list>` as the pseudo checkbox will then ignore the color class set for the individual list option. Closes #15234
This commit is contained in:
committed by
Jeremy Elbourn
parent
48d17afc14
commit
66d38fc596
@@ -120,13 +120,14 @@
|
||||
(ngModelChange)="onSelectedOptionsChange($event)"
|
||||
(change)="changeEventCount = changeEventCount + 1"
|
||||
[disabled]="selectionListDisabled"
|
||||
[disableRipple]="selectionListRippleDisabled">
|
||||
[disableRipple]="selectionListRippleDisabled"
|
||||
color="primary">
|
||||
<h3 mat-subheader>Groceries</h3>
|
||||
|
||||
<mat-list-option value="bananas" checkboxPosition="before">Bananas</mat-list-option>
|
||||
<mat-list-option selected value="oranges">Oranges</mat-list-option>
|
||||
<mat-list-option value="apples">Apples</mat-list-option>
|
||||
<mat-list-option value="strawberries">Strawberries</mat-list-option>
|
||||
<mat-list-option value="apples" color="accent">Apples</mat-list-option>
|
||||
<mat-list-option value="strawberries" color="warn">Strawberries</mat-list-option>
|
||||
</mat-selection-list>
|
||||
|
||||
<mat-selection-list [disableRipple]="selectionListRippleDisabled">
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
ViewChildren,
|
||||
} from '@angular/core';
|
||||
import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
|
||||
import {MatRipple, defaultRippleAnimationConfig} from '@angular/material/core';
|
||||
import {MatRipple, defaultRippleAnimationConfig, ThemePalette} from '@angular/material/core';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {
|
||||
MatListModule,
|
||||
@@ -123,6 +123,33 @@ describe('MatSelectionList without forms', () => {
|
||||
expect(listOptions[2].nativeElement.getAttribute('aria-disabled')).toBe('false');
|
||||
});
|
||||
|
||||
it('should be able to specify a color for list options', () => {
|
||||
const optionNativeElements = listOptions.map(option => option.nativeElement);
|
||||
|
||||
expect(optionNativeElements.every(option => !option.classList.contains('mat-primary')))
|
||||
.toBe(true);
|
||||
expect(optionNativeElements.every(option => !option.classList.contains('mat-warn')))
|
||||
.toBe(true);
|
||||
|
||||
// All options will be set to the "warn" color.
|
||||
fixture.componentInstance.selectionListColor = 'warn';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(optionNativeElements.every(option => !option.classList.contains('mat-primary')))
|
||||
.toBe(true);
|
||||
expect(optionNativeElements.every(option => option.classList.contains('mat-warn')))
|
||||
.toBe(true);
|
||||
|
||||
// Color will be set explicitly for an option and should take precedence.
|
||||
fixture.componentInstance.firstOptionColor = 'primary';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(optionNativeElements[0].classList).toContain('mat-primary');
|
||||
expect(optionNativeElements[0].classList).not.toContain('mat-warn');
|
||||
expect(optionNativeElements.slice(1).every(option => option.classList.contains('mat-warn')))
|
||||
.toBe(true);
|
||||
});
|
||||
|
||||
it('should be able to deselect an option', () => {
|
||||
let testListItem = listOptions[2].injector.get<MatListOption>(MatListOption);
|
||||
let selectList =
|
||||
@@ -1122,8 +1149,10 @@ describe('MatSelectionList with forms', () => {
|
||||
<mat-selection-list
|
||||
id="selection-list-1"
|
||||
(selectionChange)="onValueChange($event)"
|
||||
[disableRipple]="listRippleDisabled">
|
||||
<mat-list-option checkboxPosition="before" disabled="true" value="inbox">
|
||||
[disableRipple]="listRippleDisabled"
|
||||
[color]="selectionListColor">
|
||||
<mat-list-option checkboxPosition="before" disabled="true" value="inbox"
|
||||
[color]="firstOptionColor">
|
||||
Inbox (disabled selection-option)
|
||||
</mat-list-option>
|
||||
<mat-list-option id="testSelect" checkboxPosition="before" class="test-native-focus"
|
||||
@@ -1140,6 +1169,8 @@ describe('MatSelectionList with forms', () => {
|
||||
class SelectionListWithListOptions {
|
||||
showLastOption: boolean = true;
|
||||
listRippleDisabled = false;
|
||||
selectionListColor: ThemePalette;
|
||||
firstOptionColor: ThemePalette;
|
||||
|
||||
onValueChange(_change: MatSelectionListChange) {}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
MatLine,
|
||||
setLines,
|
||||
mixinDisableRipple,
|
||||
ThemePalette,
|
||||
} from '@angular/material/core';
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
import {Subscription} from 'rxjs';
|
||||
@@ -97,6 +98,11 @@ export class MatSelectionListChange {
|
||||
'tabindex': '-1',
|
||||
'[class.mat-list-item-disabled]': 'disabled',
|
||||
'[class.mat-list-item-with-avatar]': '_avatar || _icon',
|
||||
// Manually set the "primary" or "warn" class if the color has been explicitly
|
||||
// set to "primary" or "warn". The pseudo checkbox picks up these classes for
|
||||
// its theme. The accent theme palette is the default and doesn't need to be set.
|
||||
'[class.mat-primary]': 'color === "primary"',
|
||||
'[class.mat-warn]': 'color === "warn"',
|
||||
'[attr.aria-selected]': 'selected.toString()',
|
||||
'[attr.aria-disabled]': 'disabled.toString()',
|
||||
},
|
||||
@@ -121,6 +127,12 @@ export class MatListOption extends _MatListOptionMixinBase
|
||||
/** Whether the label should appear before or after the checkbox. Defaults to 'after' */
|
||||
@Input() checkboxPosition: 'before' | 'after' = 'after';
|
||||
|
||||
/** Theme color of the list option. This sets the color of the checkbox. */
|
||||
@Input()
|
||||
get color(): ThemePalette { return this._color || this.selectionList.color; }
|
||||
set color(newValue: ThemePalette) { this._color = newValue; }
|
||||
private _color: ThemePalette;
|
||||
|
||||
/** Value of the option */
|
||||
@Input()
|
||||
get value(): any { return this._value; }
|
||||
@@ -316,6 +328,9 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
|
||||
/** Tabindex of the selection list. */
|
||||
@Input() tabIndex: number = 0;
|
||||
|
||||
/** Theme color of the selection list. This sets the checkbox color for all list options. */
|
||||
@Input() color: ThemePalette = 'accent';
|
||||
|
||||
/**
|
||||
* Function used for comparing an option against the selected value when determining which
|
||||
* options should appear as selected. The first argument is the value of an options. The second
|
||||
@@ -389,8 +404,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const disableRippleChanges = changes.disableRipple;
|
||||
const colorChanges = changes.color;
|
||||
|
||||
if (disableRippleChanges && !disableRippleChanges.firstChange) {
|
||||
if ((disableRippleChanges && !disableRippleChanges.firstChange) ||
|
||||
(colorChanges && !colorChanges.firstChange)) {
|
||||
this._markOptionsForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -48,6 +48,7 @@ export declare class MatListOption extends _MatListOptionMixinBase implements Af
|
||||
_lines: QueryList<MatLine>;
|
||||
_text: ElementRef;
|
||||
checkboxPosition: 'before' | 'after';
|
||||
color: ThemePalette;
|
||||
disabled: any;
|
||||
selected: boolean;
|
||||
selectionList: MatSelectionList;
|
||||
@@ -84,6 +85,7 @@ export declare class MatNavList extends _MatListMixinBase implements CanDisableR
|
||||
export declare class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {
|
||||
_keyManager: FocusKeyManager<MatListOption>;
|
||||
_onTouched: () => void;
|
||||
color: ThemePalette;
|
||||
compareWith: (o1: any, o2: any) => boolean;
|
||||
disabled: boolean;
|
||||
options: QueryList<MatListOption>;
|
||||
|
||||
Reference in New Issue
Block a user