Skip to content

Commit

Permalink
fix(material/checkbox): no color assigned if defaults don't have a co…
Browse files Browse the repository at this point in the history
…lor (#21042)

Fixes an issue where a `mat-checkbox` wouldn't have a `color`, if the
`MAT_CHECKBOX_DEFAULT_OPTIONS` was provided without one.

Fixes #21031.

(cherry picked from commit 5e9cc5f)
  • Loading branch information
crisbeto authored and wagnermaciel committed Nov 17, 2020
1 parent c598fe2 commit c1a65c3
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 63 deletions.
46 changes: 22 additions & 24 deletions src/material-experimental/mdc-checkbox/checkbox.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
MatCheckboxChange,
MatCheckboxModule
} from './index';
import {MAT_CHECKBOX_DEFAULT_OPTIONS} from '@angular/material/checkbox';
import {MatCheckboxDefaultOptions, MAT_CHECKBOX_DEFAULT_OPTIONS} from '@angular/material/checkbox';


describe('MDC-based MatCheckbox', () => {
Expand Down Expand Up @@ -992,45 +992,43 @@ describe('MDC-based MatCheckbox', () => {

describe('MatCheckboxDefaultOptions', () => {
describe('when MAT_CHECKBOX_DEFAULT_OPTIONS overridden', () => {
beforeEach(() => {
function configure(defaults: MatCheckboxDefaultOptions) {
TestBed.configureTestingModule({
imports: [MatCheckboxModule, FormsModule],
declarations: [SingleCheckbox, SingleCheckbox],
providers: [{
provide: MAT_CHECKBOX_DEFAULT_OPTIONS,
useValue: {color: 'primary'},
}],
providers: [{provide: MAT_CHECKBOX_DEFAULT_OPTIONS, useValue: defaults}]
});

TestBed.compileComponents();
});
}

it('should override default color in component', () => {
const fixture: ComponentFixture<SingleCheckbox> =
TestBed.createComponent(SingleCheckbox);
configure({color: 'primary'});
const fixture: ComponentFixture<SingleCheckbox> = TestBed.createComponent(SingleCheckbox);
fixture.detectChanges();
const checkboxDebugElement: DebugElement =
fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(
checkboxDebugElement.nativeElement.classList
).toContain('mat-primary');
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-primary');
});

it('should not override explicit input bindings', () => {
const fixture: ComponentFixture<SingleCheckbox> =
TestBed.createComponent(SingleCheckbox);
configure({color: 'primary'});
const fixture: ComponentFixture<SingleCheckbox> = TestBed.createComponent(SingleCheckbox);
fixture.componentInstance.checkboxColor = 'warn';
fixture.detectChanges();
const checkboxDebugElement: DebugElement =
fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(
checkboxDebugElement.nativeElement.classList
).not.toContain('mat-primary');
expect(
checkboxDebugElement.nativeElement.classList
).toContain('mat-warn');
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).not.toContain('mat-primary');
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-warn');
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-warn');
});

it('should default to accent if config does not specify color', () => {
configure({clickAction: 'noop'});
const fixture: ComponentFixture<SingleCheckbox> = TestBed.createComponent(SingleCheckbox);
fixture.componentInstance.checkboxColor = undefined;
fixture.detectChanges();
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-accent');
});
});
});

Expand Down
15 changes: 7 additions & 8 deletions src/material-experimental/mdc-checkbox/checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {
MAT_CHECKBOX_DEFAULT_OPTIONS,
MatCheckboxDefaultOptions
MatCheckboxDefaultOptions, MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY
} from '@angular/material/checkbox';
import {
ThemePalette,
Expand All @@ -46,6 +46,9 @@ import {numbers} from '@material/ripple';

let nextUniqueId = 0;

// Default checkbox configuration.
const defaults = MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY();

export const MAT_CHECKBOX_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MatCheckbox),
Expand Down Expand Up @@ -110,7 +113,7 @@ export class MatCheckbox extends _MatCheckboxMixinBase implements AfterViewInit,
@Input('aria-describedby') ariaDescribedby: string;

/** The color palette for this checkbox ('primary', 'accent', or 'warn'). */
@Input() color: ThemePalette = 'accent';
@Input() color: ThemePalette;

/** Whether the label should appear after or before the checkbox. Defaults to 'after'. */
@Input() labelPosition: 'before'|'after' = 'after';
Expand Down Expand Up @@ -258,12 +261,8 @@ export class MatCheckbox extends _MatCheckboxMixinBase implements AfterViewInit,
// ripple, which we do ourselves instead.
this.tabIndex = parseInt(tabIndex) || 0;
this._checkboxFoundation = new MDCCheckboxFoundation(this._checkboxAdapter);

this._options = this._options || {};

if (this._options.color) {
this.color = this.defaultColor = this._options.color;
}
this._options = this._options || defaults;
this.color = this.defaultColor = this._options!.color || defaults.color;
}

ngAfterViewInit() {
Expand Down
46 changes: 22 additions & 24 deletions src/material/checkbox/checkbox.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from './index';
import {MutationObserverFactory} from '@angular/cdk/observers';
import {ThemePalette} from '@angular/material/core';
import {MatCheckboxDefaultOptions} from './checkbox-config';


describe('MatCheckbox', () => {
Expand Down Expand Up @@ -1201,45 +1202,42 @@ describe('MatCheckbox', () => {

describe('MatCheckboxDefaultOptions', () => {
describe('when MAT_CHECKBOX_DEFAULT_OPTIONS overridden', () => {
beforeEach(() => {
function configure(defaults: MatCheckboxDefaultOptions) {
TestBed.configureTestingModule({
imports: [MatCheckboxModule, FormsModule],
declarations: [SingleCheckbox, SimpleCheckbox],
providers: [{
provide: MAT_CHECKBOX_DEFAULT_OPTIONS,
useValue: {color: 'primary'},
}],
providers: [{provide: MAT_CHECKBOX_DEFAULT_OPTIONS, useValue: defaults}]
});

TestBed.compileComponents();
});
}

it('should override default color in component', () => {
const fixture: ComponentFixture<SimpleCheckbox> =
TestBed.createComponent(SimpleCheckbox);
fixture.detectChanges();
const checkboxDebugElement: DebugElement =
fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(
checkboxDebugElement.nativeElement.classList
).toContain('mat-primary');
configure({color: 'primary'});
const fixture: ComponentFixture<SimpleCheckbox> = TestBed.createComponent(SimpleCheckbox);
fixture.detectChanges();
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-primary');
});

it('should not override explicit input bindings', () => {
const fixture: ComponentFixture<SingleCheckbox> =
TestBed.createComponent(SingleCheckbox);
configure({color: 'primary'});
const fixture: ComponentFixture<SingleCheckbox> = TestBed.createComponent(SingleCheckbox);
fixture.componentInstance.checkboxColor = 'warn';
fixture.detectChanges();
const checkboxDebugElement: DebugElement =
fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(
checkboxDebugElement.nativeElement.classList
).not.toContain('mat-primary');
expect(
checkboxDebugElement.nativeElement.classList
).toContain('mat-warn');
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).not.toContain('mat-primary');
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-warn');
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-warn');
});

it('should default to accent if config does not specify color', () => {
configure({clickAction: 'noop'});
const fixture: ComponentFixture<SimpleCheckbox> = TestBed.createComponent(SimpleCheckbox);
fixture.detectChanges();
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
expect(checkboxDebugElement.nativeElement.classList).toContain('mat-accent');
});
});
});

Expand Down
14 changes: 7 additions & 7 deletions src/material/checkbox/checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ import {
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
import {
MAT_CHECKBOX_DEFAULT_OPTIONS,
MatCheckboxDefaultOptions
MatCheckboxDefaultOptions,
MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY,
} from './checkbox-config';


// Increasing integer for generating unique ids for checkbox components.
let nextUniqueId = 0;

// Default checkbox configuration.
const defaults = MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY();

/**
* Provider Expression that allows mat-checkbox to register as a ControlValueAccessor.
* This allows it to support [(ngModel)].
Expand Down Expand Up @@ -204,12 +208,8 @@ export class MatCheckbox extends _MatCheckboxMixinBase implements ControlValueAc
@Optional() @Inject(MAT_CHECKBOX_DEFAULT_OPTIONS)
private _options?: MatCheckboxDefaultOptions) {
super(elementRef);
this._options = this._options || {};

if (this._options.color) {
this.color = this.defaultColor = this._options.color;
}

this._options = this._options || defaults;
this.color = this.defaultColor = this._options.color || defaults.color;
this.tabIndex = parseInt(tabIndex) || 0;
}

Expand Down

0 comments on commit c1a65c3

Please sign in to comment.