From 5034c1d7298fff9d2dc8f06ee9be79546b1d7bce Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 13 Feb 2016 00:32:08 -0600 Subject: [PATCH] fix(toggle): use value accessor provider Remove the value property and always recommend ngModel or ngControl. Closes #5425 --- ionic/components/toggle/test/basic/index.ts | 12 +- ionic/components/toggle/test/basic/main.html | 26 +-- ionic/components/toggle/toggle.ts | 180 +++++++++---------- 3 files changed, 107 insertions(+), 111 deletions(-) diff --git a/ionic/components/toggle/test/basic/index.ts b/ionic/components/toggle/test/basic/index.ts index 2e4e3c4691e..aa9d73f3cdb 100644 --- a/ionic/components/toggle/test/basic/index.ts +++ b/ionic/components/toggle/test/basic/index.ts @@ -15,6 +15,12 @@ import { templateUrl: 'main.html' }) class E2EApp { + fruitsForm: ControlGroup; + grapeDisabled: boolean; + kiwiModel: boolean; + strawberryModel: boolean; + formResults: string; + constructor() { this.fruitsForm = new ControlGroup({ "appleCtrl": new Control(), @@ -24,13 +30,13 @@ class E2EApp { }); this.grapeDisabled = true; - this.grapeChecked = true; - this.myModel = true; + this.kiwiModel = false; + this.strawberryModel = true; } toggleGrapeChecked() { - this.grapeChecked = !this.grapeChecked; + this.fruitsForm.controls['grapeCtrl'].updateValue( !this.fruitsForm.controls['grapeCtrl'].value ) } toggleGrapeDisabled() { diff --git a/ionic/components/toggle/test/basic/main.html b/ionic/components/toggle/test/basic/main.html index e5089207c11..cd80d285337 100644 --- a/ionic/components/toggle/test/basic/main.html +++ b/ionic/components/toggle/test/basic/main.html @@ -1,7 +1,6 @@ Toggles -
@@ -9,33 +8,33 @@ - Apple, value=apple, init checked - + Apple, ngControl + - Banana, init no checked/value attributes + Banana, ngControl - Cherry, value=cherry, init disabled - + Cherry, ngControl, disabled + - Grape, value=grape, init checked, disabled - + Grape, ngControl, checked, disabled + - Secondary color - + Kiwi, NgModel false, Secondary color + - I'm an NgModel - + Strawberry, NgModel true + @@ -57,7 +56,8 @@ cherry.value: {{fruitsForm.controls.cherryCtrl.value}}
grape.dirty: {{fruitsForm.controls.grapeCtrl.dirty}}
grape.value: {{fruitsForm.controls.grapeCtrl.value}}
- ngModel.value: {{myModel}}
+ kiwiModel: {{kiwiModel}}
+ strawberryModel: {{strawberryModel}}

diff --git a/ionic/components/toggle/toggle.ts b/ionic/components/toggle/toggle.ts index 2a0554e10be..704cb52bc66 100644 --- a/ionic/components/toggle/toggle.ts +++ b/ionic/components/toggle/toggle.ts @@ -1,13 +1,16 @@ -import {Component, ElementRef, Renderer, Input, Optional} from 'angular2/core'; -import {NgControl} from 'angular2/common'; +import {Component, ElementRef, Renderer, Input, Optional, Provider, Injector, forwardRef} from 'angular2/core'; +import {NgControl, ControlValueAccessor, NG_VALUE_ACCESSOR} from 'angular2/common'; import {Form} from '../../util/form'; -import {Config} from '../../config/config'; import {isTrueProperty} from '../../util/util'; import {Item} from '../item/item'; import {pointerCoord} from '../../util/dom'; +const TOGGLE_VALUE_ACCESSOR = new Provider( + NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => Toggle), multi: true}); + + /** * @name Toggle * @description @@ -16,11 +19,11 @@ import {pointerCoord} from '../../util/dom'; * Toggles can also have colors assigned to them, by adding any color * attribute. * - * See the [Angular 2 Docs](https://angular.io/docs/js/latest/api/forms/) for more info on forms and input. - * @property {any} [value] - the inital value of the toggle + * See the [Angular 2 Docs](https://angular.io/docs/ts/latest/guide/forms.html) + * for more info on forms and input. * @property {boolean} [checked] - whether the toggle it toggled or not * @property {boolean} [disabled] - whether the toggle is disabled or not - * @property {string} [id] - a unique ID for a toggle + * * @usage * ```html * @@ -28,26 +31,27 @@ import {pointerCoord} from '../../util/dom'; * * * Pepperoni - * + * * * * * Sausage - * + * * * * * Mushrooms - * + * * * * * ``` + * * @demo /docs/v2/demos/toggle/ * @see {@link /docs/v2/components#toggle Toggle Component Docs} */ @Component({ - selector: 'ion-toggle,ion-switch', + selector: 'ion-toggle', template: '
' + '
' + @@ -68,47 +72,31 @@ import {pointerCoord} from '../../util/dom'; '', host: { '[class.toggle-disabled]': '_disabled' - } + }, + providers: [TOGGLE_VALUE_ACCESSOR] }) -export class Toggle { +export class Toggle implements ControlValueAccessor { private _checked: any = false; private _disabled: any = false; private _labelId: string; private _activated: boolean = false; - private _mode: string; - private _startX; - private _touched: number = 0; + private _startX: number; + private _msPrv: number = 0; + private _fn: Function; /** * @private */ id: string; - /** - * @private - */ - @Input() value: string = ''; - constructor( private _form: Form, private _elementRef: ElementRef, private _renderer: Renderer, - config: Config, - @Optional() ngControl: NgControl, - @Optional() private _item: Item + @Optional() private _item: Item, + private _injector: Injector ) { - // deprecated warning - if (_elementRef.nativeElement.tagName == 'ION-SWITCH') { - console.warn(' has been renamed to , please update your HTML'); - } - - _form.register(this); - - this._mode = config.get('mode'); - - if (ngControl) { - ngControl.valueAccessor = this; - } + this._form.register(this); if (_item) { this.id = 'tgl-' + _item.registerInput('toggle'); @@ -117,57 +105,15 @@ export class Toggle { } } - /** - * @private - * Toggle the checked state of this toggle. - */ - toggle() { - this.checked = !this.checked; - } - - /** - * @private - */ - @Input() - get checked() { - return this._checked; - } - - set checked(val) { - if (!this._disabled) { - this._checked = isTrueProperty(val); - this.onChange(this._checked); - this._item && this._item.setCssClass('item-toggle-checked', this._checked); - } - } - - /** - * @private - */ - @Input() - get disabled() { - return this._disabled; - } - - set disabled(val) { - this._disabled = isTrueProperty(val); - this._item && this._item.setCssClass('item-toggle-disabled', this._disabled); - } - /** * @private */ private pointerDown(ev) { - if (ev.type.indexOf('touch') > -1) { - this._touched = Date.now(); - } - - if (this.isDisabled(ev)) { + if (this._isPrevented(ev)) { return; } this._startX = pointerCoord(ev).x; - this._activated = true; } @@ -176,18 +122,24 @@ export class Toggle { */ private pointerMove(ev) { if (this._startX) { + if (this._isPrevented(ev)) { + return; + } + let currentX = pointerCoord(ev).x; - console.debug('toggle move', ev.type, currentX); + console.debug('toggle, pointerMove', ev.type, currentX); if (this._checked) { if (currentX + 15 < this._startX) { - this.toggle(); + this.onChange(false); this._startX = currentX; + this._activated = true; } } else if (currentX - 15 > this._startX) { - this.toggle(); + this.onChange(true); this._startX = currentX; + this._activated = (currentX < this._startX + 5); } } } @@ -198,7 +150,7 @@ export class Toggle { private pointerUp(ev) { if (this._startX) { - if (this.isDisabled(ev)) { + if (this._isPrevented(ev)) { return; } @@ -206,10 +158,11 @@ export class Toggle { if (this.checked) { if (this._startX + 4 > endX) { - this.toggle(); + this.onChange(false); } + } else if (this._startX - 4 < endX) { - this.toggle(); + this.onChange(true); } this._activated = false; @@ -217,36 +170,67 @@ export class Toggle { } } + @Input() + get checked(): any { + return this._checked; + } + + set checked(val: any) { + this._setChecked(isTrueProperty(val)); + this.onChange(this._checked); + } + /** * @private */ - writeValue(value) { - this.checked = value; + writeValue(val: any) { + this._setChecked( isTrueProperty(val) ); } /** * @private */ - onChange(val) { - // TODO: figure the whys and the becauses + registerOnChange(fn: Function): void { + this._fn = fn; + this.onChange = (isChecked: boolean) => { + console.debug('toggle, onChange', isChecked); + fn(isChecked); + this._setChecked(isChecked); + }; } /** * @private */ - onTouched(val) { - // TODO: figure the whys and the becauses + private _setChecked(isChecked: boolean) { + this._checked = isChecked; + this._item && this._item.setCssClass('item-toggle-checked', isChecked); + } + + @Input() + get disabled(): any { + return this._disabled; + } + + set disabled(val: any) { + this._disabled = isTrueProperty(val); + this._item && this._item.setCssClass('item-toggle-disabled', this._disabled); } /** * @private */ - registerOnChange(fn) { this.onChange = fn; } + registerOnTouched(fn) { this.onTouched = fn; } /** * @private */ - registerOnTouched(fn) { this.onTouched = fn; } + onChange(_) {} + + /** + * @private + */ + onTouched() {} /** * @private @@ -258,9 +242,15 @@ export class Toggle { /** * @private */ - private isDisabled(ev) { - return (this._touched + 999 > Date.now() && (ev.type.indexOf('mouse') > -1)) - || (this._mode == 'ios' && ev.target.tagName == 'ION-TOGGLE'); + private _isPrevented(ev) { + if (ev.type.indexOf('touch') > -1) { + this._msPrv = Date.now() + 2000; + + } else if (this._msPrv > Date.now() && ev.type.indexOf('mouse') > -1) { + ev.preventDefault(); + ev.stopPropagation(); + return true; + } } }