diff --git a/ionic/components/checkbox/checkbox.scss b/ionic/components/checkbox/checkbox.scss
index 30dabefa0b..8653bfbe95 100644
--- a/ionic/components/checkbox/checkbox.scss
+++ b/ionic/components/checkbox/checkbox.scss
@@ -5,7 +5,6 @@
.checkbox {
position: relative;
- display: block;
cursor: pointer;
@include user-select-none();
}
@@ -21,6 +20,10 @@
@include appearance(none);
}
+.checkbox .input-label {
+ max-width: 100%;
+}
+
.checkbox[aria-disabled=true] {
opacity: 0.5;
color: gray;
diff --git a/ionic/components/checkbox/checkbox.ts b/ionic/components/checkbox/checkbox.ts
index a705ea12a2..99c816731d 100644
--- a/ionic/components/checkbox/checkbox.ts
+++ b/ionic/components/checkbox/checkbox.ts
@@ -18,7 +18,7 @@ import {Icon} from '../icon/icon';
@IonicComponent({
selector: 'ion-checkbox',
host: {
- '[class.item]': 'item',
+ 'class': 'item',
'[attr.aria-checked]': 'input.checked'
}
})
@@ -46,8 +46,6 @@ export class Checkbox extends IonInputItem {
this.cd = cd;
cd.valueAccessor = this;
-
- this.item = true;
}
onInit() {
diff --git a/ionic/components/form/label.scss b/ionic/components/form/label.scss
index 6f951f44da..01fb3c600f 100644
--- a/ionic/components/form/label.scss
+++ b/ionic/components/form/label.scss
@@ -2,14 +2,12 @@
// Label
// --------------------------------------------------
-$input-label-color: #444 !default;
+$input-label-color: #888 !default;
.input-label {
display: block;
max-width: 200px;
- //width: 30%;
- //min-width: 100px;
color: $input-label-color;
font-size: inherit;
white-space: nowrap;
diff --git a/ionic/components/form/label.ts b/ionic/components/form/label.ts
index a89b651a5b..4086ddeada 100644
--- a/ionic/components/form/label.ts
+++ b/ionic/components/form/label.ts
@@ -5,6 +5,7 @@ import * as dom from '../../util/dom';
import {Input} from './text-input';
import {Checkbox} from '../checkbox/checkbox';
import {RadioButton} from '../radio/radio';
+import {Switch} from '../switch/switch';
@Directive({
@@ -23,9 +24,10 @@ export class Label {
@Optional() @Parent() textContainer: Input,
@Optional() @Parent() checkboxContainer: Checkbox,
@Optional() @Parent() radioContainer: RadioButton,
+ @Optional() @Parent() switchContainer: Switch,
config: IonicConfig
) {
- this.container = textContainer || checkboxContainer || radioContainer;
+ this.container = textContainer || checkboxContainer || radioContainer || switchContainer;
if (this.container) {
this.container.registerLabel(this);
diff --git a/ionic/components/form/test/fixed-inline-labels/main.html b/ionic/components/form/test/fixed-inline-labels/main.html
index 2e273a83f1..9755bcce34 100644
--- a/ionic/components/form/test/fixed-inline-labels/main.html
+++ b/ionic/components/form/test/fixed-inline-labels/main.html
@@ -19,6 +19,9 @@
+
@@ -27,16 +30,19 @@
+
+
+
@@ -49,6 +55,7 @@
+
diff --git a/ionic/components/form/test/inline-labels/main.html b/ionic/components/form/test/inline-labels/main.html
index fe8507d7e4..2f1ebfa8bf 100644
--- a/ionic/components/form/test/inline-labels/main.html
+++ b/ionic/components/form/test/inline-labels/main.html
@@ -19,6 +19,9 @@
+
@@ -27,16 +30,19 @@
+
+
+
@@ -44,11 +50,13 @@
+
+
diff --git a/ionic/components/item/extensions/ios.scss b/ionic/components/item/extensions/ios.scss
index ba74243c70..04bc251e04 100644
--- a/ionic/components/item/extensions/ios.scss
+++ b/ionic/components/item/extensions/ios.scss
@@ -83,6 +83,10 @@ $item-ios-note-color: #999 !default;
font-size: 1.3rem;
}
+ .item-input .input + button {
+ margin-top: $item-ios-padding-media-top;
+ }
+
.badge {
margin-right: $item-ios-padding-right;
}
diff --git a/ionic/components/item/item.scss b/ionic/components/item/item.scss
index 3683f65d9b..ce92d42e42 100644
--- a/ionic/components/item/item.scss
+++ b/ionic/components/item/item.scss
@@ -73,6 +73,8 @@ button.item.item {
.item-content + .item-media,
.item-content + .item-content,
icon + .input,
+ .input + icon,
+ icon + .input-label,
.input-label + .input {
margin-left: 0;
}
diff --git a/ionic/components/radio/radio.ts b/ionic/components/radio/radio.ts
index e5777d51c7..f046e5ce6a 100644
--- a/ionic/components/radio/radio.ts
+++ b/ionic/components/radio/radio.ts
@@ -71,7 +71,7 @@ export class RadioGroup extends Ion {
@IonicComponent({
selector: 'ion-radio',
host: {
- '[class.item]': 'item',
+ 'class': 'item',
'[attr.aria-checked]': 'input.checked',
}
})
@@ -91,7 +91,6 @@ export class RadioButton extends IonInputItem {
config: IonicConfig
) {
super(elementRef, config);
- this.item = true;
this.group = group;
}
diff --git a/ionic/components/switch/extensions/ios.scss b/ionic/components/switch/extensions/ios.scss
index 313197f726..fab87b26ad 100644
--- a/ionic/components/switch/extensions/ios.scss
+++ b/ionic/components/switch/extensions/ios.scss
@@ -2,37 +2,86 @@
// iOS Switch
// --------------------------------------------------
-$switch-ios-width: 52px !default;
-$switch-ios-height: 32px !default;
-$switch-ios-slider-off-background: #fff !default;
-$switch-ios-slider-on-background: #4cd964 !default;
-$switch-ios-toggle-on-background: #fff !default;
+$switch-ios-width: 51px !default;
+$switch-ios-height: 31px !default;
+$switch-ios-border-width: 2px !default;
+$switch-ios-border-radius: 30px !default;
+
+$switch-ios-off-bg-color: #fff !default;
+$switch-ios-off-border-color: #e6e6e6 !default;
+
+$switch-ios-on-bg-color: get-color(primary, base) !default;
+$switch-ios-on-border-color: $switch-ios-on-bg-color !default;
+
+$switch-ios-handle-width: $switch-ios-height - ($switch-ios-border-width * 2) !default;
+$switch-ios-handle-height: $switch-ios-handle-width !default;
+$switch-ios-handle-radius: $switch-ios-handle-width !default;
+$switch-ios-handle-dragging-bg-color: darken(#fff, 5%) !default;
+$switch-ios-handle-box-shadow: 0 3px 12px rgba(0, 0, 0, 0.16), 0 3px 1px rgba(0, 0, 0, 0.1), 0px 0px 1px rgba(0, 0, 0, 0.15) !default;
+
+$switch-ios-handle-off-bg-color: #fff !default;
+$switch-ios-handle-on-bg-color: #fff !default;
+
+$switch-ios-hit-area-expansion: 5px !default;
.switch[mode="ios"] {
- .switch-toggle {
+ .media-switch {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ }
+
+ .switch-track {
+ /*@include transition-timing-function(ease-in-out);
+ @include transition-duration($switch-ios-transition-duration);
+ @include transition-property((background-color, border));*/
+ position: relative;
width: $switch-ios-width;
height: $switch-ios-height;
- border-radius: $switch-ios-height / 2;
-
- background: #e5e5e5;
+ border: solid $switch-ios-border-width $switch-ios-off-border-color;
+ border-radius: $switch-ios-border-radius;
+ background-color: $switch-ios-off-bg-color;
+ content: ' ';
+ cursor: pointer;
+ pointer-events: none;
}
- .switch-toggle:before {
- background: $switch-ios-slider-off-background;
+ .switch-handle {
+ //@include transition($switch-ios-transition-duration cubic-bezier(0, 1.1, 1, 1.1));
+ //@include transition-property((background-color, transform));
+
+ position: absolute;
+
+ width: $switch-ios-handle-width;
+ height: $switch-ios-handle-height;
+ border-radius: $switch-ios-handle-radius;
+ background-color: $switch-ios-handle-off-bg-color;
+ top: 0;
+ left: 0;
+ box-shadow: $switch-ios-handle-box-shadow;
+
+ &:before {
+ position: absolute;
+ top: -4px;
+ left: ( ($switch-ios-handle-width / 2) * -1) - 8;
+ padding: ($switch-ios-handle-height / 2) + 5 ($switch-ios-handle-width + 7);
+ content: '';
+ }
}
- .switch-toggle:after {
- box-shadow: 0 2px 5px rgba(0,0,0,.4);
+ &[aria-checked=true] .switch-track {
+ background-color: $switch-ios-on-bg-color;
+ border-color: $switch-ios-on-border-color;
}
- &[aria-checked=true] .switch-toggle {
- background: $switch-ios-slider-on-background;
+ &[aria-checked=true] .switch-handle {
+ background-color: $switch-ios-handle-on-bg-color;
+ transform: translate3d($switch-ios-width - $switch-ios-handle-width - ($switch-ios-border-width * 2), 0, 0);
}
- &[aria-checked=true] .switch-toggle:before {
- transform: scale(0);
+ .input-label {
+ color: inherit;
}
}
diff --git a/ionic/components/switch/switch.scss b/ionic/components/switch/switch.scss
index 8f18ea5b23..4a418bc61c 100644
--- a/ionic/components/switch/switch.scss
+++ b/ionic/components/switch/switch.scss
@@ -2,73 +2,29 @@
// Switch
// --------------------------------------------------
-$switch-padding: 0 15px !default;
-$switch-width: 52px !default;
-$switch-height: 32px !default;
-$switch-border-width: 2px !default;
-$switch-slider-off-background: #ccc !default;
-$switch-slider-on-background: #387ef5 !default;
-$switch-toggle-on-background: #fff !default;
-
-.switch .item-media {
- padding: $switch-padding;
-}
-
-.switch-toggle {
+.switch {
position: relative;
-
- width: $switch-width;
- height: $switch-height;
- border-radius: $switch-height / 2;
-
- background: $switch-slider-off-background;
+ cursor: pointer;
+ @include user-select-none();
}
-.switch-toggle:before {
+.switch input {
position: absolute;
- left: $switch-border-width;
- top: $switch-border-width;
-
- width: $switch-width - ($switch-border-width * 2);
- height: $switch-height - ($switch-border-width * 2);
- border-radius: $switch-height / 2;
-
- transition-duration: 300ms;
- content: ' ';
+ width: 0;
+ height: 0;
+ margin: 0;
+ padding: 0;
+ opacity: 0;
+ border: none;
+ @include appearance(none);
}
-.switch[aria-checked=true] .switch-toggle {
- background: $switch-slider-on-background;
-}
-
-.switch .switch-toggle:after {
- position: absolute;
- left: $switch-border-width;
- top: $switch-border-width;
-
- width: $switch-height - ($switch-border-width * 2);
- height: $switch-height - ($switch-border-width * 2);
-
- border-radius: $switch-height - ($switch-border-width * 2);
- background: $switch-toggle-on-background;
-
- transition-duration: 300ms;
-
- content: ' ';
-}
-
-.switch[aria-checked=true] .switch-toggle:after {
- transform: translate3d(20px,0,0);
+.switch .input-label {
+ max-width: 100%;
}
.switch[aria-disabled=true] {
- pointer-events: none;
opacity: 0.5;
color: gray;
}
-
-.switch .item-media,
-.switch .item-content {
- pointer-events: none;
-}
diff --git a/ionic/components/switch/switch.ts b/ionic/components/switch/switch.ts
index 5f90bc7eb6..6b7f08ae82 100644
--- a/ionic/components/switch/switch.ts
+++ b/ionic/components/switch/switch.ts
@@ -1,71 +1,127 @@
-import {View, ElementRef} from 'angular2/angular2';
-import {ControlGroup, ControlDirective} from 'angular2/forms';
+import {
+ View,
+ Directive,
+ ElementRef,
+ Renderer,
+ Optional,
+ Parent,
+ NgControl
+} from 'angular2/angular2';
import {Ion} from '../ion';
+import {IonInputItem} from '../form/input';
import {IonicConfig} from '../../config/config';
-import {IonicComponent} from '../../config/annotations';
+import {IonicComponent, IonicView} from '../../config/annotations';
+import {Icon} from '../icon/icon';
@IonicComponent({
selector: 'ion-switch',
- properties: [
- 'checked'
- ],
host: {
- '(click)': 'switchClicked($event)',
- 'class': 'item'
+ 'class': 'item',
+ //'[attr.aria-checked]': 'input.checked'
}
})
-@View({
- template: `
- `
+@IonicView({
+ template:
+ '' +
+ '' +
+ '
' +
+ ''
})
-export class Switch extends Ion {
+export class Switch extends IonInputItem {
constructor(
+ @Optional() cd: NgControl,
+ renderer: Renderer,
elementRef: ElementRef,
- ionicConfig: IonicConfig
- //cd: ControlDirective
+ config: IonicConfig
) {
- super(elementRef, ionicConfig)
+ super(elementRef, config);
+ this.onChange = (_) => {};
+ this.onTouched = (_) => {};
+ this.renderer = renderer;
+ this.elementRef = elementRef;
+ this.cd = cd;
- // this.config = Switch.config.invoke(this)
- // this.controlDirective = cd;
- // cd.valueAccessor = this;
-
- // TODO: These rely on the commented-out PropertySetter's above
- //setAriaRole('checkbox')
- //setInvalid('false')
- //setDisabled('false')
- //this.setCheckedProperty = setAriaChecked
+ if(cd) cd.valueAccessor = this;
}
- /**
- * Much like ngModel, this is called from our valueAccessor for the attached
- * ControlDirective to update the value internally.
- */
- writeValue(value) {
- // Convert it to a boolean
- this.checked = !!value;
+ onInit() {
+ super.onInit();
+ console.log("switch onInit")
}
- set checked(checked) {
- this._checked = checked
- //this.setCheckedProperty(checked)
- this.controlDirective._control().updateValue(this._checked);
+ onAllChangesDone() {
+ return
+ console.log("switch onAllChangesDone")
+ if (this._checked !== void 0 && this.input.checked != this._checked) {
+ if (this.input.checked !== void 0) {
+ console.warn("switch 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("switch 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});
}
- get checked() {
- return this._checked
+ //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});
}
- switchClicked(ev) {
- this.checked = !this.checked;
+ // Called by the model (Control) to update the view
+ writeValue(modelValue) {
+ 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; }
}
diff --git a/ionic/components/switch/test/basic/e2e.ts b/ionic/components/switch/test/basic/e2e.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/ionic/components/switch/test/basic/index.ts b/ionic/components/switch/test/basic/index.ts
index 99de26004d..e906bafacf 100644
--- a/ionic/components/switch/test/basic/index.ts
+++ b/ionic/components/switch/test/basic/index.ts
@@ -1,24 +1,32 @@
-import {FormBuilder, Validators} from 'angular2/forms';
-
import {App} from 'ionic/ionic';
-
+import {
+ Control,
+ ControlGroup,
+ NgForm,
+ formDirectives,
+ Validators,
+ NgControl,
+ ControlValueAccessor,
+ NgControlName,
+ NgFormModel,
+ FormBuilder
+} from 'angular2/forms';
@App({
templateUrl: 'main.html'
})
class IonicApp {
constructor() {
-
- var fb = new FormBuilder();
- this.form = fb.group({
- enableFun: ['', Validators.required],
- enableIceCream: [false, Validators.required],
- enablePizza: [true, Validators.required]
+ this.fruitsForm = new ControlGroup({
+ "appleCtrl": new Control({"checked": false, "value": "apple"}),
+ "bananaCtrl": new Control(true),
+ "cherryCtrl": new Control({"checked": false, "value": 12}),
+ "grapeCtrl": new Control("grape")
});
}
doSubmit(ev) {
- console.log('Submitting form', this.form.value);
- ev.preventDefault();
+ console.log('Submitting form', this.fruitsForm.value);
+ event.preventDefault();
}
}
diff --git a/ionic/components/switch/test/basic/main.html b/ionic/components/switch/test/basic/main.html
index bdb5c1cb63..494af7bb30 100644
--- a/ionic/components/switch/test/basic/main.html
+++ b/ionic/components/switch/test/basic/main.html
@@ -1,25 +1,35 @@
+
+Switches
+
+
-
diff --git a/ionic/config/annotations.ts b/ionic/config/annotations.ts
index c623c26a36..6beddb1f4d 100644
--- a/ionic/config/annotations.ts
+++ b/ionic/config/annotations.ts
@@ -65,7 +65,7 @@ export const IonicDirectives = [
forwardRef(() => Checkbox),
forwardRef(() => RadioGroup),
forwardRef(() => RadioButton),
- //Switch
+ forwardRef(() => Switch),
//SearchBar,
// Input