diff --git a/src/components/switch/switch.spec.ts b/src/components/switch/switch.spec.ts index be87b80d9664..3e450e0dc515 100644 --- a/src/components/switch/switch.spec.ts +++ b/src/components/switch/switch.spec.ts @@ -16,7 +16,7 @@ import {MdSwitch} from './switch'; import {AsyncTestFn} from "angular2/testing"; import {FORM_DIRECTIVES} from "angular2/common"; import {Input} from "angular2/core"; - +import {By} from 'angular2/platform/browser'; describe('MdSwitch', () => { let builder: TestComponentBuilder; @@ -24,10 +24,10 @@ describe('MdSwitch', () => { beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { builder = tcb; })); describe('md-switch', () => { - it('should change the model value', (done: () => void) => { + it('should change the model value', (done:() => void) => { return builder.createAsync(TestApp).then((fixture) => { let testComponent = fixture.debugElement.componentInstance; - let switchElement = getChildDebugElement(fixture.debugElement, 'md-switch'); + let switchElement = fixture.debugElement.query(By.css('md-switch')); expect(switchElement.nativeElement.classList.contains('md-checked')).toBe(false); @@ -39,21 +39,34 @@ describe('MdSwitch', () => { done(); }); }); + + it('should not change the model if disabled', (done:() => void) => { + return builder.createAsync(TestApp).then((fixture) => { + let testComponent = fixture.debugElement.componentInstance; + let switchElement = fixture.debugElement.query(By.css('md-switch')); + + expect(switchElement.nativeElement.classList.contains('md-checked')).toBe(false); + + testComponent.isDisabled = true; + fixture.detectChanges(); + + switchElement.nativeElement.click(); + + expect(switchElement.nativeElement.classList.contains('md-checked')).toBe(false); + done(); + }); + }); }); }); -/** Gets a child DebugElement by tag name. */ -function getChildDebugElement(parent: DebugElement, tagName: string): DebugElement { - return parent.query(debugEl => debugEl.nativeElement.tagName.toLowerCase() == tagName); -} - /** Test component that contains an MdSwitch. */ @Component({ selector: 'test-app', directives: [MdSwitch, FORM_DIRECTIVES], template: - 'Test Switch', + 'Test Switch', }) class TestApp { testSwitch = false; + isDisabled = false; } diff --git a/src/components/switch/switch.ts b/src/components/switch/switch.ts index 3873edccfc22..473d72289c93 100644 --- a/src/components/switch/switch.ts +++ b/src/components/switch/switch.ts @@ -3,10 +3,13 @@ import {MdDrag} from '../../core/services/drag/drag'; import {ControlValueAccessor} from "angular2/common"; import {NgControl} from "angular2/common"; import {Optional} from "angular2/core"; +import {Renderer} from "angular2/core"; @Component({ selector: 'md-switch', + inputs: ['disabled'], host: { + '[attr.aria-disabled]': 'disabled', '(click)': 'onClick()' }, templateUrl: './components/switch/switch.html', @@ -27,10 +30,12 @@ export class MdSwitch implements ControlValueAccessor { onChange = (_:any) => {}; onTouched = () => {}; - // Model Values - value: boolean; + // storage values + checked_: any; + disabled_: boolean; - constructor(private _elementRef: ElementRef, @Optional() ngControl: NgControl) { + constructor(private _elementRef: ElementRef, private _renderer: Renderer, @Optional() ngControl: NgControl) { + this.componentElement = _elementRef.nativeElement; this.elementRef = _elementRef; if (ngControl) { @@ -39,7 +44,6 @@ export class MdSwitch implements ControlValueAccessor { } ngOnInit() { - this.componentElement = this.elementRef.nativeElement; this.switchContainer = this.componentElement.querySelector('.md-container'); this.thumbContainer = this.componentElement.querySelector('.md-thumb-container'); @@ -48,10 +52,13 @@ export class MdSwitch implements ControlValueAccessor { this.switchContainer.addEventListener('$md.dragstart', (ev: CustomEvent) => this.onDragStart(ev)); this.switchContainer.addEventListener('$md.drag', (ev: CustomEvent) => this.onDrag(ev)); this.switchContainer.addEventListener('$md.dragend', (ev: CustomEvent) => this.onDragEnd(ev)); + } onDragStart(event: CustomEvent) { + if (this.disabled) return; + this.componentElement.classList.add('md-dragging'); this.dragData = { @@ -62,9 +69,11 @@ export class MdSwitch implements ControlValueAccessor { } onDrag(event: CustomEvent) { + if (this.disabled) return; + let percent = event.detail.pointer.distanceX / this.dragData.width; - let translate = this.value ? 1 + percent : percent; + let translate = this.checked ? 1 + percent : percent; translate = Math.max(0, Math.min(1, translate)); this.thumbContainer.style.transform = 'translate3d(' + (100 * translate) + '%,0,0)'; @@ -72,13 +81,15 @@ export class MdSwitch implements ControlValueAccessor { } onDragEnd(event: CustomEvent) { + if (this.disabled) return; + this.componentElement.classList.remove('md-dragging'); this.thumbContainer.style.transform = null; - var isChanged = this.value ? this.dragData.translate < 0.5 : this.dragData.translate > 0.5; + var isChanged = this.checked ? this.dragData.translate < 0.5 : this.dragData.translate > 0.5; if (isChanged || !this.dragData.translate) { - this.changeValue(!this.value); + this.checked = !this.checked; } this.dragData = null; @@ -89,19 +100,14 @@ export class MdSwitch implements ControlValueAccessor { } onClick() { - if (!this.dragClick) this.changeValue(!this.value); + if (!this.dragClick && !this.disabled) { + this.checked = !this.checked; + } } - changeValue(newValue: boolean) { - this.onChange(newValue); - this.writeValue(newValue); - } writeValue(value: any): void { - this.value = !!value; - - // Apply Checked Class - this.componentElement.classList.toggle('md-checked', this.value); + this.checked = value; } registerOnChange(fn: any): void { @@ -111,4 +117,31 @@ export class MdSwitch implements ControlValueAccessor { registerOnTouched(fn: any): void { this.onTouched = fn; } + + get disabled(): string|boolean { + return this.disabled_; + } + + set disabled(value: string|boolean) { + if (typeof value == 'string') { + this.disabled_ = (value === 'true' || value === ''); + } else { + this.disabled_ = value; + } + + this._renderer.setElementAttribute(this._elementRef, 'disabled', this.disabled_ ? 'true' : undefined); + } + + get checked() { + return !!this.checked_; + } + + set checked(value) { + this.checked_ = !!value; + this.onChange(this.checked_); + + this._renderer.setElementAttribute(this._elementRef, 'aria-checked', this.checked_); + this.componentElement.classList.toggle('md-checked', this.checked); + } + } \ No newline at end of file diff --git a/src/demo-app/demo-app.html b/src/demo-app/demo-app.html index 79f13fe18d1d..eaee60a3d002 100644 --- a/src/demo-app/demo-app.html +++ b/src/demo-app/demo-app.html @@ -5,6 +5,6 @@ - Toggle Angular Version + Toggle Angular Version Value: {{ switchValue }}