-
{
promiseCompleter.resolve();
});
+ // Events are only triggered when the element has focus
+ checkboxInstance.hasFocus = true;
+
testComponent.isChecked = true;
fixture.detectChanges();
@@ -296,10 +299,25 @@ describe('MdCheckbox', () => {
});
}));
+ it('should NOT call the change event when it doesn\'t have focus', fakeAsync(() => {
+ fixture.detectChanges();
+ expect(testComponent.lastEvent).toBeUndefined();
+
+ checkboxInstance.checked = true;
+ fixture.detectChanges();
+
+ tick();
+
+ expect(testComponent.lastEvent).toBeUndefined();
+ }));
+
it('should call the change event on first change after initialization', fakeAsync(() => {
fixture.detectChanges();
expect(testComponent.lastEvent).toBeUndefined();
+ // Events are only triggered when the element has focus
+ checkboxInstance.hasFocus = true;
+
checkboxInstance.checked = true;
fixture.detectChanges();
@@ -312,6 +330,9 @@ describe('MdCheckbox', () => {
fixture.detectChanges();
expect(testComponent.lastEvent).toBeUndefined();
+ // Events are only triggered when the element has focus
+ checkboxInstance.hasFocus = true;
+
// Trigger the click on the inputElement, because the input will probably
// emit a DOM event to the change output.
inputElement.click();
diff --git a/src/components/checkbox/checkbox.ts b/src/components/checkbox/checkbox.ts
index e343466a5d92..b44c8126e83f 100644
--- a/src/components/checkbox/checkbox.ts
+++ b/src/components/checkbox/checkbox.ts
@@ -7,6 +7,7 @@ import {
Output,
Provider,
Renderer,
+ ViewChild,
ViewEncapsulation,
forwardRef,
AfterContentInit
@@ -113,6 +114,8 @@ export class MdCheckbox implements AfterContentInit, ControlValueAccessor {
/** Event emitted when the checkbox's `checked` value changes. */
@Output() change: EventEmitter
= new EventEmitter();
+ @ViewChild('input') _inputElement: ElementRef;
+
/** Called when the checkbox is blurred. Needed to properly implement ControlValueAccessor. */
onTouched: () => any = () => {};
@@ -149,7 +152,7 @@ export class MdCheckbox implements AfterContentInit, ControlValueAccessor {
this._checked ? TransitionCheckState.Checked : TransitionCheckState.Unchecked);
// Only fire a change event if this isn't the first time the checked property is ever set.
- if (this._isInitialized) {
+ if (this._isInitialized && this.hasFocus) {
this._emitChangeEvent();
}
}
@@ -177,6 +180,7 @@ export class MdCheckbox implements AfterContentInit, ControlValueAccessor {
this._indeterminate = indeterminate;
if (this._indeterminate) {
this._transitionCheckState(TransitionCheckState.Indeterminate);
+ this._checked = false;
} else {
this._transitionCheckState(
this.checked ? TransitionCheckState.Checked : TransitionCheckState.Unchecked);
diff --git a/src/demo-app/checkbox/checkbox-demo.ts b/src/demo-app/checkbox/checkbox-demo.ts
index af331d4e91f6..04ec81fe3e41 100644
--- a/src/demo-app/checkbox/checkbox-demo.ts
+++ b/src/demo-app/checkbox/checkbox-demo.ts
@@ -48,13 +48,18 @@ export class MdCheckboxDemoNestedChecklist {
: task.completed;
}
- someComplete(tasks: Task[]): boolean {
- const numComplete = tasks.filter(t => t.completed).length;
- return numComplete > 0 && numComplete < tasks.length;
+ someComplete(task: Task): boolean {
+ const subtasks = task.subtasks;
+ const numComplete = subtasks.filter(t => t.completed).length;
+ return numComplete > 0 && numComplete < subtasks.length;
}
- setAllCompleted(tasks: Task[], completed: boolean) {
- tasks.forEach(t => t.completed = completed);
+ setAllCompleted(task: Task) {
+ task.subtasks.forEach(t => t.completed = task.completed);
+ }
+
+ resetParent(task: Task) {
+ task.completed = this.allComplete(task);
}
}
diff --git a/src/demo-app/checkbox/nested-checklist.html b/src/demo-app/checkbox/nested-checklist.html
index 4b721ab99759..a09f16ff3d30 100644
--- a/src/demo-app/checkbox/nested-checklist.html
+++ b/src/demo-app/checkbox/nested-checklist.html
@@ -2,14 +2,13 @@ Tasks
-
+ [indeterminate]="someComplete(task)"
+ (change)="setAllCompleted(task)">
{{task.name}}