Skip to content

Commit 5caa8ed

Browse files
committed
Only set indeterminate when user clicked on checkbox
1 parent 3b2f66d commit 5caa8ed

File tree

2 files changed

+48
-18
lines changed

2 files changed

+48
-18
lines changed

src/lib/checkbox/checkbox.spec.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ describe('MdCheckbox', () => {
101101
expect(inputElement.indeterminate).toBe(false);
102102
});
103103

104-
it('should set indeterminate to false when set checked', async(() => {
104+
it('should set indeterminate to false when input clicked', async(() => {
105105
testComponent.isIndeterminate = true;
106106
fixture.detectChanges();
107107

108108
expect(checkboxInstance.indeterminate).toBe(true);
109109
expect(inputElement.indeterminate).toBe(true);
110110
expect(testComponent.isIndeterminate).toBe(true);
111111

112-
testComponent.isChecked = true;
112+
inputElement.click();
113113
fixture.detectChanges();
114114

115115
fixture.whenStable().then(() => {
@@ -127,7 +127,7 @@ describe('MdCheckbox', () => {
127127
expect(inputElement.checked).toBe(true);
128128
expect(testComponent.isIndeterminate).toBe(true);
129129

130-
testComponent.isChecked = false;
130+
inputElement.click();
131131
fixture.detectChanges();
132132

133133
fixture.whenStable().then(() => {
@@ -141,6 +141,38 @@ describe('MdCheckbox', () => {
141141

142142
}));
143143

144+
it('should not set indeterminate to false when checked is set programmatically', async(() => {
145+
testComponent.isIndeterminate = true;
146+
fixture.detectChanges();
147+
148+
expect(checkboxInstance.indeterminate).toBe(true);
149+
expect(inputElement.indeterminate).toBe(true);
150+
expect(testComponent.isIndeterminate).toBe(true);
151+
152+
testComponent.isChecked = true;
153+
fixture.detectChanges();
154+
155+
fixture.whenStable().then(() => {
156+
fixture.detectChanges();
157+
expect(checkboxInstance.checked).toBe(true);
158+
expect(inputElement.indeterminate).toBe(true);
159+
expect(inputElement.checked).toBe(true);
160+
expect(testComponent.isIndeterminate).toBe(true);
161+
162+
testComponent.isChecked = false;
163+
fixture.detectChanges();
164+
165+
fixture.whenStable().then(() => {
166+
fixture.detectChanges();
167+
expect(checkboxInstance.checked).toBe(false);
168+
expect(inputElement.indeterminate).toBe(true);
169+
expect(inputElement.checked).toBe(false);
170+
expect(testComponent.isIndeterminate).toBe(true);
171+
});
172+
});
173+
174+
}));
175+
144176
it('should change native element checked when check programmatically', () => {
145177
expect(inputElement.checked).toBe(false);
146178

@@ -216,11 +248,11 @@ describe('MdCheckbox', () => {
216248
expect(checkboxInstance.checked).toBe(false);
217249
});
218250

219-
it('should overwrite indeterminate state when checked is re-set', async(() => {
251+
it('should overwrite indeterminate state when clicked', async(() => {
220252
testComponent.isIndeterminate = true;
221253
fixture.detectChanges();
222254

223-
testComponent.isChecked = true;
255+
inputElement.click();
224256
fixture.detectChanges();
225257

226258
fixture.whenStable().then(() => {

src/lib/checkbox/checkbox.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -210,21 +210,14 @@ export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestro
210210
}
211211

212212
/**
213-
* Whether the checkbox is checked. Note that setting `checked` will immediately set
214-
* `indeterminate` to false.
213+
* Whether the checkbox is checked.
215214
*/
216215
@Input() get checked() {
217216
return this._checked;
218217
}
219218

220219
set checked(checked: boolean) {
221220
if (checked != this.checked) {
222-
if (this._indeterminate) {
223-
Promise.resolve().then(() => {
224-
this._indeterminate = false;
225-
this.indeterminateChange.emit(this._indeterminate);
226-
});
227-
}
228221
this._checked = checked;
229222
this._changeDetectorRef.markForCheck();
230223
}
@@ -233,11 +226,8 @@ export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestro
233226
/**
234227
* Whether the checkbox is indeterminate. This is also known as "mixed" mode and can be used to
235228
* represent a checkbox with three states, e.g. a checkbox that represents a nested list of
236-
* checkable items. Note that whenever `checked` is set, indeterminate is immediately set to
237-
* false. This differs from the web platform in that indeterminate state on native
238-
* checkboxes is only remove when the user manually checks the checkbox (rather than setting the
239-
* `checked` property programmatically). However, we feel that this behavior is more accommodating
240-
* to the way consumers would envision using this component.
229+
* checkable items. Note that whenever checkbox is manually clicked, indeterminate is immediately
230+
* set to false.
241231
*/
242232
@Input() get indeterminate() {
243233
return this._indeterminate;
@@ -374,6 +364,14 @@ export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestro
374364
this._removeFocusedRipple();
375365

376366
if (!this.disabled) {
367+
// When user manually click on the checkbox, `indeterminate` is set to false.
368+
if (this._indeterminate) {
369+
Promise.resolve().then(() => {
370+
this._indeterminate = false;
371+
this.indeterminateChange.emit(this._indeterminate);
372+
});
373+
}
374+
377375
this.toggle();
378376
this._transitionCheckState(
379377
this._checked ? TransitionCheckState.Checked : TransitionCheckState.Unchecked);

0 commit comments

Comments
 (0)