checkbox and radio

This commit is contained in:
Tim Lancina
2015-07-17 15:41:01 -05:00
parent 2ed18de699
commit cb5fa23a80
7 changed files with 157 additions and 158 deletions

View File

@ -17,8 +17,9 @@ import {Icon} from '../icon/icon';
@IonicComponent({
selector: 'ion-checkbox',
host: {
'class': 'item',
'[attr.aria-checked]': 'checked'
'[class.item]': 'item',
'[attr.aria-checked]': 'input.checked',
'(^click)': 'onClick($event)'
},
defaultProperties: {
'iconOff': 'ion-ios-circle-outline',
@ -27,7 +28,7 @@ import {Icon} from '../icon/icon';
})
@IonicView({
template:
'<div class="item-media media-checkbox" (click)="onClick($event)">' +
'<div class="item-media media-checkbox">' +
'<icon [name]="iconOff" class="checkbox-off"></icon>' +
'<icon [name]="iconOn" class="checkbox-on"></icon>' +
'</div>' +
@ -36,42 +37,31 @@ import {Icon} from '../icon/icon';
'</div>'
})
export class Checkbox extends IonInputItem {
_checkbox: CheckboxInput;
constructor(
elementRef: ElementRef,
config: IonicConfig
) {
super(elementRef, config);
this.item = true;
}
onAllChangesDone() {
// Enforce that this directive actually contains a checkbox
if (this._checkbox == null) {
throw 'No <input type="checkbox"> found inside of <ion-checkbox>';
}
}
onClick(ev) {
// toggling with spacebar fires mouse event
if (ev.target.tagName === "INPUT") return;
registerInput(checkboxDir) {
if (this._checkbox != null) {
throw 'Only one <input type="checkbox"> is allowed per <ion-checkbox>'
}
this._checkbox = checkboxDir.elementRef.nativeElement;
this._checkboxDir = checkboxDir;
}
this.input.checked = !this.input.checked;
onClick(e) {
let val = !this._checkbox.checked;
this._checkbox.checked = val;
this.checked = val;
//TODO figure out a way to trigger change on the actual input to trigger
//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;
}
}

View File

@ -1,7 +1,4 @@
import {Component, View} from 'angular2/angular2';
import {Query, QueryList, NgFor} from 'angular2/angular2';
// import {FormBuilder, Validators, NgFormControl, Control, NgControlName, NgControlGroup, ControlContainer} from 'angular2/forms';
import {App} from 'ionic/ionic';
import {
Control,
ControlGroup,
@ -14,8 +11,6 @@ import {
NgFormModel,
FormBuilder
} from 'angular2/forms';
import {App, Checkbox, Content, List} from 'ionic/ionic';
//import {IONIC_DIRECTIVES} from 'ionic/ionic'
@App({
templateUrl: 'main.html'

View File

@ -9,12 +9,18 @@ import {RadioButton} from '../radio/radio';
@Directive({
selector: 'input[type=checkbox],input[type=radio]'
selector: 'input[type=checkbox],input[type=radio]',
properties: [ 'checked', 'name' ],
host: {
'[checked]': 'checked',
'[attr.name]': 'name',
'(change)': 'onChangeEvent($event)'
}
})
export class TapInput extends IonInput {
constructor(
@Optional() @Parent() checkboxContainer: Checkbox, //TODO have this be either Checkbox or Radio
@Optional() @Parent() radioContainer : RadioButton,
@Optional() @Parent() checkboxContainer: Checkbox,
@Optional() @Parent() radioContainer: RadioButton,
@Optional() @Ancestor() scrollView: Content,
@Attribute('type') type: string,
elementRef: ElementRef,
@ -35,4 +41,8 @@ export class TapInput extends IonInput {
this.tabIndex = this.tabIndex || '';
}
onChangeEvent(ev) {
this.container && this.container.onChangeEvent(this);
}
}

View File

@ -1,134 +1,105 @@
import {ElementRef, Ancestor} from 'angular2/angular2';
import {IonicDirective, IonicComponent, IonicView} from '../../config/annotations';
import {IonicConfig} from '../../config/config';
import {Ion} from '../ion';
import {IonInputItem} from '../form/form';
let groupName = -1;
@IonicDirective({
selector: 'ion-radio-group'
selector: 'ion-radio-group',
host: {
'[class.list]': 'list'
}
})
export class RadioGroup {
export class RadioGroup extends Ion {
_name: number = ++groupName;
buttons: Array<RadioButton> = [];
constructor(
elementRef: ElementRef//,
//cd:ControlDirective
elementRef: ElementRef,
ionicConfig: IonicConfig
) {
this.ele = elementRef.nativeElement
// this.config = RadioGroup.config.invoke(this)
// this.controlDirective = cd;
// cd.valueAccessor = this; //ControlDirective should inject CheckboxControlDirective
this.ele.classList.add('list');
this.buttons = [];
super(elementRef, ionicConfig);
this.list = true;
}
/**
* Much like ngModel, this is called from our valueAccessor for the attached
* ControlDirective to update the value internally.
*/
writeValue(value) {
this.value = value;
setTimeout(() => {
this.selectFromValue(value);
})
}
/**
* Called by child SegmentButtons to bind themselves to
* the Segment.
*/
register(radioButton) {
this.buttons.push(radioButton);
let inputEl = radioButton.input.elementRef.nativeElement;
if (!inputEl.hasAttribute('name')) {
radioButton.input.name = this._name;
}
// if (radioButton && !radioButton.hasAttribute('name')){
// radioButton.setAttribute('name', this._name);
// }
}
// If we don't have a default value, and this is the
// first button added, select it
if(!this.value && this.buttons.length === 1) {
setTimeout(() => {
// We need to defer so the control directive can initialize
this.selected(radioButton);
})
update(input) {
for (let button of this.buttons) {
button.input.checked = button.input.elementRef.nativeElement.checked;
}
}
/**
* Select the button with the given value.
*/
selectFromValue(value) {
for(let button of this.buttons) {
if(button.value === value) {
this.selected(button);
}
}
}
/**
* Indicate a button should be selected.
*/
selected(radioButton) {
for(let button of this.buttons) {
button.setActive(false);
}
radioButton.setActive(true);
this.value = radioButton.value;
// TODO: Better way to do this?
this.controlDirective._control().updateValue(this.value);
}
}
@IonicComponent({
selector: 'ion-radio',
properties: [
'value'
],
host: {
'(^click)': 'buttonClicked($event)'
'[class.item]': 'item',
'[class.active]': 'input.checked',
'[attr.aria-checked]': 'input.checked',
'(^click)': 'onClick($event)'
},
defaultProperties: {
'iconOff': 'ion-ios-circle-outline',
'iconOn': 'ion-ios-checkmark'
}
})
@IonicView({
template: `
<div class="item-content">
<div class="item-title">
<content></content>
</div>
<div class="item-media media-radio">
<icon class="radio-off"></icon>
<icon class="ion-ios-checkmark-empty radio-on"></icon>
</div>
</div>
`
template:
'<div class="item-media media-radio">' +
'<icon [name]="iconOff" class="radio-off"></icon>' +
'<icon [name]="iconOn" class="radio-on"></icon>' +
'</div>' +
'<div class="item-content">' +
'<content></content>' +
'</div>'
})
export class RadioButton {
export class RadioButton extends IonInputItem {
constructor(
@Ancestor() group: RadioGroup,
elementRef: ElementRef
elementRef: ElementRef,
config: IonicConfig
) {
this.ele = elementRef.ele;
this.ele.classList.add('item')
this.ele.setAttribute('aria-checked', true)
super(elementRef, config);
this.item = true;
this.group = group;
group.register(this);
}
setActive(isActive) {
// TODO: No ele
if(isActive) {
this.ele.classList.add('active');
this.ele.setAttribute('aria-checked', true)
} else {
this.ele.classList.remove('active');
this.ele.setAttribute('aria-checked', false)
}
registerInput(input) {
this.input = input;
this.group.register(this);
}
buttonClicked(event) {
this.group.selected(this, event);
event.preventDefault();
onClick(ev) {
// switching between radio buttons with arrow keys fires a MouseEvent
if (ev.target.tagName === "INPUT") return;
this.input.checked = !this.input.checked;
//let bindings update first
setTimeout(() => this.group.update(this.input));
//TODO figure out a way to trigger change on the actual input to trigger
// form updates
// this._checkbox.dispatchEvent(e);
//this._checkboxDir.control.valueAccessor.writeValue(val);
}
onChangeEvent(input) {
this.group.update(input);
}
}

View File

@ -1,4 +1,16 @@
import {App} from 'ionic/ionic';
import {
Control,
ControlGroup,
NgForm,
formDirectives,
Validators,
NgControl,
ControlValueAccessor,
NgControlName,
NgFormModel,
FormBuilder
} from 'angular2/forms';
@App({
@ -6,9 +18,33 @@ import {App} from 'ionic/ionic';
})
class IonicApp {
constructor() {
// var fb = new FormBuilder();
// this.form = fb.group({
// preferredApple: ['mac', Validators.required],
// });
this.fruitsGroup1 = new ControlGroup({
"appleCtrl": new Control("", isChecked),
"bananaCtrl": new Control("", isChecked)
});
this.fruitsGroup2 = new ControlGroup({
"grapeCtrl": new Control("", isChecked),
"cherryCtrl": new Control("", isChecked)
});
this.fruitsForm = new ControlGroup({
"fruitGroup1": this.fruitsGroup1,
"fruitGroup2": this.fruitsGroup2
});
function isChecked(ctrl) {
if (ctrl.checked) {
return null;
} else {
return {
'notChecked': true
}
}
}
}
doSubmit(event) {
console.log('Submitting form', this.fruitsForm.value);
event.preventDefault();
}
}

View File

@ -3,33 +3,28 @@
<ion-content>
<form (^submit)="doSubmit($event)" [control-group]="form">
<form (^submit)="doSubmit($event)" [ng-form-model]="fruitsForm">
<div class="list-header">
Radio Group
Fruit Group 1
</div>
<ion-radio-group control="preferredApple">
<ion-radio value="mac">
McIntosh
</ion-radio>
<ion-radio value="granny">
Granny Smith
</ion-radio>
<ion-radio value="gala">
Gala
</ion-radio>
<ion-radio value="fuji">
Fuji
</ion-radio>
<ion-radio-group ng-control-group="fruitGroup1">
<ion-radio><label>APPLE</label><input #apple type="radio" ng-control="appleCtrl"></ion-radio>
<ion-radio><label>BANANA</label><input #banana type="radio" ng-control="bananaCtrl"></ion-radio>
</ion-radio-group>
appleCtrl.dirty: {{fruitsForm.controls.fruitGroup1.controls.appleCtrl.dirty}}<br>
<div class="list-header">
Fruit Group 2
</div>
<ion-radio-group ng-control-group="fruitGroup2">
<ion-radio><label>GRAPE</label><input #grape name="test" type="radio" ng-control="grapeCtrl"></ion-radio>
<ion-radio><label>CHERRY</label><input #cherry name="test" type="radio" ng-control="cherryCtrl"></ion-radio>
</ion-radio-group>
</form>
Current apple: <b>{{form.controls.preferredApple.value}}</b>
</ion-content>
</ion-view>

View File

@ -57,8 +57,10 @@ export const IonicDirectives = [
forwardRef(() => SegmentButton),
forwardRef(() => SegmentControlValueAccessor),
forwardRef(() => Checkbox),
//Checkbox, Switch
//RadioGroup, RadioButton, SearchBar,
forwardRef(() => RadioGroup),
forwardRef(() => RadioButton),
//Switch
//SearchBar,
// Input
forwardRef(() => Input),