From 0770abfc44de359efdaa951c71091243e0d52448 Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Mon, 27 Jul 2015 15:22:40 -0500 Subject: [PATCH] checkbox wip --- ionic/components/checkbox/checkbox.ts | 124 ++++++++++++------ ionic/components/checkbox/test/basic/index.ts | 32 +---- .../components/checkbox/test/basic/main.html | 43 +++--- ionic/components/form/input.ts | 8 +- ionic/components/form/label.ts | 5 +- ionic/components/form/tap-input.ts | 11 +- ionic/components/form/text-input.ts | 3 + ionic/components/radio/radio.ts | 12 +- 8 files changed, 130 insertions(+), 108 deletions(-) diff --git a/ionic/components/checkbox/checkbox.ts b/ionic/components/checkbox/checkbox.ts index b1d2203fd0..98840c9959 100644 --- a/ionic/components/checkbox/checkbox.ts +++ b/ionic/components/checkbox/checkbox.ts @@ -2,6 +2,7 @@ import { View, Directive, ElementRef, + Renderer, Optional, Parent, NgControl @@ -18,8 +19,7 @@ import {Icon} from '../icon/icon'; selector: 'ion-checkbox', host: { '[class.item]': 'item', - '[attr.aria-checked]': 'input.checked', - // '(^click)': 'onClick($event)' + '[attr.aria-checked]': 'input.checked' }, defaultProperties: { 'iconOff': 'ion-ios-circle-outline', @@ -29,7 +29,8 @@ import {Icon} from '../icon/icon'; @IonicView({ template: '
' + - '
' + + '' + + '' + '
' + '
' + '' + @@ -37,50 +38,95 @@ import {Icon} from '../icon/icon'; }) export class Checkbox extends IonInputItem { constructor( + cd: NgControl, + renderer: Renderer, elementRef: ElementRef, config: IonicConfig ) { super(elementRef, config); + this.onChange = (_) => {}; + this.onTouched = (_) => {}; + this.renderer = renderer; + this.elementRef = elementRef; + this.cd = cd; + + cd.valueAccessor = this; + this.item = true; } - // onClick(ev) { - // debugger - // // toggling with spacebar fires mouse event - // if (ev.target.tagName === "INPUT") return; - // - // this.input.checked = !this.input.checked; - // - // //TODO trigger change/mouse event on the actual input to trigger - // // form updates - // - // // this._checkbox.dispatchEvent(e); - // //this._checkboxDir.control.valueAccessor.writeValue(val); - // } - - onChangeEvent(input) { - //TODO can we just assume this will always be true? - this.input.checked = this.input.elementRef.nativeElement.checked; + onInit() { + super.onInit(); + console.log("checkbox onInit") } - focus() { - let mouseClick = new MouseEvent("click", { - bubbles: true, - cancelable: true, - }); - this.input && this.input.elementRef.nativeElement.dispatchEvent(mouseClick); + onAllChangesDone() { + console.log("checkbox onAllChangesDone") + if (this._checked !== void 0 && this.input.checked != this._checked) { + if (this.input.checked !== void 0) { + console.warn("Checkbox checked is set in view template and Control declaration.\n" + + "Value: " + !!this._checked + " from Control takes precedence"); + } + this.input.checked = !!this._checked; + } + if (this._value !== void 0 && this.input.value != this._value) { + if (this.input.value !== void 0) { + console.warn("Checkbox value is set in view template and Control declaration.\n" + + "Value: " + this._value + " from Control takes precedence"); + } + this.input.value = this._value; + } + if (this.input.value === void 0) { + this.input.value = "on"; + } + if (this.input.checked === void 0) { + this.input.checked = false; + } + //TODO check validity + this.cd.control._value = {"checked": !!this.input.checked, "value": this.input.value}; + + //TODO only want to call this once, we want to set input.checked directly on subsequent + // writeValue's + this.onAllChangesDone = () => {}; + // this.onChange({"checked": this.input.checked, "value": this.input.value}); } + + //from clicking the label or selecting with keyboard + //view -> model (Control) + toggle() { + this.input.checked = this._checked = !this.input.checked; + this.onChange({"checked": this.input.checked, "value": this.input.value}); + } + + // Called by the model (Control) to update the view + writeValue(modelValue) { + debugger; + let type = typeof modelValue; + switch (type) { + case "boolean": + // don't set input.value here, do it in onAllChangesDone + // because they might have set it in the view + this._checked = modelValue; break; + case "object": + if (modelValue.checked !== void 0) this._checked = !!modelValue.checked; + if (modelValue.value !== void 0) this._value = modelValue.value.toString(); + break; + default: + // don't set input.checked here, do it in onAllChangesDone + // because they might have set it in the view + this._value = modelValue.toString(); + } + + //TODO we want to set input.checked directly after the first time + console.log("writeValue, " + this.input.id + " checked: " + this._checked); + console.log("writeValue " + this.input.id + " value: " + this._value); + + // this.cd.control._value = {"checked": this.input.checked, "value": this.input.value}; + } + + // Used by the view to update the model (Control) + // Up to us to call it in update() + registerOnChange(fn) { this.onChange = fn; } + + registerOnTouched(fn) { this.onTouched = fn; } } - - -// export class CheckboxInput { -// constructor( -// elementRef: ElementRef, -// @Optional() @Parent() container: Checkbox, -// @Optional() control: NgControl -// ) { -// this.elementRef = elementRef; -// this.control = control ? control : null; -// container && container.registerCheckbox(this); -// } -// } diff --git a/ionic/components/checkbox/test/basic/index.ts b/ionic/components/checkbox/test/basic/index.ts index 8648475d06..e906bafacf 100644 --- a/ionic/components/checkbox/test/basic/index.ts +++ b/ionic/components/checkbox/test/basic/index.ts @@ -17,37 +17,15 @@ import { }) class IonicApp { constructor() { - - // var fb = new FormBuilder(); - // this.controls = { - // appleCtrl : ['', Validators.required], - // bananaCtrl: ['', Validators.required], - // grapeCtrl: ['', Validators.required], - // cherryCtrl: ['', Validators.required] - // }; - // - // this.fruitsForm = fb.group(this.controls); - this.fruitsForm = new ControlGroup({ - "appleCtrl": new Control("", isChecked), - "bananaCtrl": new Control("", isChecked), - // "bananaCtrl": new Control("BANANA", isChecked), - // "grapeCtrl": new Control("GRAPE", isChecked), - // "cherryCtrl": new Control("CHERRY", isChecked) + "appleCtrl": new Control({"checked": false, "value": "apple"}), + "bananaCtrl": new Control(true), + "cherryCtrl": new Control({"checked": false, "value": 12}), + "grapeCtrl": new Control("grape") }); - - function isChecked(ctrl) { - if (ctrl.checked) { - return null; - } else { - return { - 'notChecked': true - } - } - } } - doSubmit(event) { + doSubmit(ev) { console.log('Submitting form', this.fruitsForm.value); event.preventDefault(); } diff --git a/ionic/components/checkbox/test/basic/main.html b/ionic/components/checkbox/test/basic/main.html index 1692e7bbe3..ec3738cd0a 100644 --- a/ionic/components/checkbox/test/basic/main.html +++ b/ionic/components/checkbox/test/basic/main.html @@ -1,30 +1,29 @@
- - - + + + + - - + +
appleCtrl.dirty: {{fruitsForm.controls.appleCtrl.dirty}}
- appleCtrl.value: {{fruitsForm.controls.appleCtrl.value}}
- apple.value: {{apple.value}}
- apple.checked: {{apple.checked}}
+ appleCtrl.value: {{fruitsForm.controls.appleCtrl.value.value}}
+ appleCtrl.checked: {{fruitsForm.controls.appleCtrl.value.checked}}
bananaCtrl.dirty: {{fruitsForm.controls.bananaCtrl.dirty}}
- bananaCtrl.value: {{fruitsForm.controls.bananaCtrl.value}}
- banana.value: {{banana.value}}
- banana.checked: {{banana.checked}} + bananaCtrl.value: {{fruitsForm.controls.bananaCtrl.value.value}}
+ bananaCtrl.checked: {{fruitsForm.controls.bananaCtrl.value.checked}}
+ cherry.dirty: {{fruitsForm.controls.cherryCtrl.dirty}}
+ cherry.value: {{fruitsForm.controls.cherryCtrl.value.value}}
+ cherry.checked: {{fruitsForm.controls.cherryCtrl.value.checked}}
+ grape.dirty: {{fruitsForm.controls.grapeCtrl.dirty}}
+ grape.value: {{fruitsForm.controls.grapeCtrl.value.value}}
+ grape.checked: {{fruitsForm.controls.grapeCtrl.value.checked}}
+ +
diff --git a/ionic/components/form/input.ts b/ionic/components/form/input.ts index 0e3a70784c..4e3d01bf16 100644 --- a/ionic/components/form/input.ts +++ b/ionic/components/form/input.ts @@ -108,7 +108,8 @@ export class IonInputItem extends Ion { itemRegistry.push(this); } - onIonInit() { + onInit() { + super.onInit(); if (this.input && this.label) { this.input.id = (this.input.id || 'input-' + this.id); this.label.labelFor = this.input.id; @@ -122,9 +123,4 @@ export class IonInputItem extends Ion { registerLabel(label) { this.label = label; } - - focus() { - this.input && this.input.focus(); - } - } diff --git a/ionic/components/form/label.ts b/ionic/components/form/label.ts index 09318e8681..a89b651a5b 100644 --- a/ionic/components/form/label.ts +++ b/ionic/components/form/label.ts @@ -33,7 +33,6 @@ export class Label { } this.scrollAssist = config.setting('keyboardScrollAssist'); - this.scrollAssist = true; //TODO get rid of this } pointerStart(ev) { @@ -44,7 +43,7 @@ export class Label { } pointerEnd(ev) { - if (this.scrollAssist && this.container) { + if (this.container) { // get where the touchend/mouseup ended let endCoord = dom.pointerCoord(ev); @@ -54,7 +53,7 @@ export class Label { ev.preventDefault(); ev.stopPropagation(); - this.container.focus(); + this.container instanceof Input ? this.container.focus() : this.container.toggle(); } this.startCoord = null; diff --git a/ionic/components/form/tap-input.ts b/ionic/components/form/tap-input.ts index 8e80f7ec92..625d1d55b7 100644 --- a/ionic/components/form/tap-input.ts +++ b/ionic/components/form/tap-input.ts @@ -15,7 +15,7 @@ import {RadioButton} from '../radio/radio'; '[checked]': 'checked', '[value]': 'value', '[attr.name]': 'name', - '(change)': 'onChangeEvent($event)', + '(change)': 'toggle()', 'class': 'tap-input input' } }) @@ -43,10 +43,15 @@ export class TapInput extends IonInput { this.tabIndex = this.tabIndex || ''; } + onInit() { + console.log("tapinput oninit, " + this.id + " checked: " + this.checked); + console.log("tapinput oninit, " + this.id + " value: " + this.value); + } + //to detect switching/selecting inputs with the keyboard //view -> model (Control) - onChangeEvent(ev) { - this.container && this.container.onChangeEvent(this); + toggle() { + this.container && this.container.toggle(this); } } diff --git a/ionic/components/form/text-input.ts b/ionic/components/form/text-input.ts index 8c95eaa29f..1350874104 100644 --- a/ionic/components/form/text-input.ts +++ b/ionic/components/form/text-input.ts @@ -26,6 +26,9 @@ export class Input extends IonInputItem { super(elementRef, ionicConfig); } + focus() { + this.input && this.input.focus(); + } } diff --git a/ionic/components/radio/radio.ts b/ionic/components/radio/radio.ts index 3c011c8a06..e22a149f20 100644 --- a/ionic/components/radio/radio.ts +++ b/ionic/components/radio/radio.ts @@ -44,6 +44,8 @@ export class RadioGroup extends Ion { } } + //from clicking the label or switching inputs with keyboard + //view -> model (Control) update(input) { for (let button of this.buttons) { button.input.checked = false; @@ -105,15 +107,9 @@ export class RadioButton extends IonInputItem { this.group.registerButton(this); } - //from clicking the label + //from clicking the label or switching inputs with keyboard //view -> model (Control) - focus() { - this.group.update(this.input); - } - - //from switching inputs with the keyboard - //view -> model (Control) - onChangeEvent() { + toggle() { this.group.update(this.input); } }