mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-07 23:16:52 +08:00
refactor(radio): native input type=radio
This commit is contained in:
18
packages/core/src/components.d.ts
vendored
18
packages/core/src/components.d.ts
vendored
@ -8,7 +8,7 @@ import 'ionicons';
|
||||
|
||||
import {
|
||||
ActionSheetButton,
|
||||
} from './components/action-sheet/action-sheet.js';
|
||||
} from './components/action-sheet/action-sheet';
|
||||
import {
|
||||
AnimationBuilder,
|
||||
PickerOptions,
|
||||
@ -18,7 +18,7 @@ import {
|
||||
import {
|
||||
AlertButton,
|
||||
AlertInput,
|
||||
} from './components/alert/alert.js';
|
||||
} from './components/alert/alert';
|
||||
import {
|
||||
ElementRef,
|
||||
Side,
|
||||
@ -26,20 +26,20 @@ import {
|
||||
import {
|
||||
GestureCallback,
|
||||
GestureDetail,
|
||||
} from './components/gesture/gesture.js';
|
||||
} from './components/gesture/gesture';
|
||||
import {
|
||||
PickerButton,
|
||||
PickerColumn as PickerColumn2,
|
||||
} from './components/picker/picker.js';
|
||||
} from './components/picker/picker';
|
||||
import {
|
||||
Event,
|
||||
} from '@stencil/core';
|
||||
import {
|
||||
ScrollCallback,
|
||||
} from './components/scroll/scroll.js';
|
||||
} from './components/scroll/scroll';
|
||||
import {
|
||||
SelectPopoverOption,
|
||||
} from './components/select/select-popover.js';
|
||||
} from './components/select/select-popover';
|
||||
|
||||
import {
|
||||
ActionSheetController as IonActionSheetController
|
||||
@ -2159,7 +2159,7 @@ declare global {
|
||||
|
||||
import {
|
||||
RadioGroup as IonRadioGroup
|
||||
} from './components/radio/radio-group';
|
||||
} from './components/radio-group/radio-group';
|
||||
|
||||
declare global {
|
||||
interface HTMLIonRadioGroupElement extends IonRadioGroup, HTMLElement {
|
||||
@ -2184,6 +2184,7 @@ declare global {
|
||||
|
||||
allowEmptySelection?: boolean,
|
||||
disabled?: boolean,
|
||||
name?: string,
|
||||
value?: string
|
||||
}
|
||||
}
|
||||
@ -2217,8 +2218,9 @@ declare global {
|
||||
|
||||
color?: string,
|
||||
mode?: 'ios' | 'md',
|
||||
checked?: boolean,
|
||||
name?: string,
|
||||
disabled?: boolean,
|
||||
checked?: boolean,
|
||||
value?: string
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { BlurEvent, BooleanInput, BooleanInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { BlurEvent, CheckboxInput, CheckedInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { Component, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChange } from '@stencil/core';
|
||||
|
||||
/**
|
||||
@ -76,7 +76,7 @@ import { Component, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChang
|
||||
theme: 'checkbox'
|
||||
}
|
||||
})
|
||||
export class Checkbox implements BooleanInput {
|
||||
export class Checkbox implements CheckboxInput {
|
||||
private checkboxId: string;
|
||||
private labelId: string;
|
||||
private styleTmr: any;
|
||||
@ -84,7 +84,7 @@ export class Checkbox implements BooleanInput {
|
||||
/**
|
||||
* @output {Event} Emitted when the checked property has changed.
|
||||
*/
|
||||
@Event() ionChange: EventEmitter<BooleanInputChangeEvent>;
|
||||
@Event() ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the toggle has focus.
|
||||
@ -123,7 +123,7 @@ export class Checkbox implements BooleanInput {
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the checkbox. Default false.
|
||||
*/
|
||||
@Prop({ mutable: true }) disabled: boolean = false;
|
||||
@Prop() disabled: boolean = false;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the checkbox.
|
||||
@ -136,13 +136,16 @@ export class Checkbox implements BooleanInput {
|
||||
}
|
||||
|
||||
@PropDidChange('checked')
|
||||
protected checkedChanged(val: boolean) {
|
||||
this.ionChange.emit({ checked: val });
|
||||
checkedChanged(isChecked: boolean) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@PropDidChange('disabled')
|
||||
protected disabledChanged() {
|
||||
disabledChanged() {
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@ -157,7 +160,6 @@ export class Checkbox implements BooleanInput {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Listen('keydown.space')
|
||||
onSpace(ev: KeyboardEvent) {
|
||||
this.toggle();
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { Component, Element, Listen, Method, Prop } from '@stencil/core';
|
||||
|
||||
import { Component, Element, Listen, Prop, State } from '@stencil/core';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
import { CssClassMap } from '../../index';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-item',
|
||||
styleUrls: {
|
||||
@ -12,15 +11,12 @@ import { CssClassMap } from '../../index';
|
||||
}
|
||||
})
|
||||
export class Item {
|
||||
private ids: number = -1;
|
||||
private itemId: string;
|
||||
private inputs: any = [];
|
||||
|
||||
private itemStyles: { [key: string]: CssClassMap } = Object.create(null);
|
||||
private label: any;
|
||||
private itemStyles: { [key: string]: CssClassMap } = {};
|
||||
|
||||
@Element() private el: HTMLElement;
|
||||
|
||||
@State() hasStyleChange: boolean;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
@ -60,27 +56,9 @@ export class Item {
|
||||
|
||||
this.itemStyles[tagName] = updatedStyles;
|
||||
|
||||
// returning true tells the renderer to queue an update
|
||||
return hasChildStyleChange;
|
||||
}
|
||||
|
||||
// TODO? this loads after radio group
|
||||
// @Listen('ionRadioDidLoad')
|
||||
// protected radioDidLoad(ev: RadioEvent) {
|
||||
// const radio = ev.detail.radio;
|
||||
// // register the input inside of the item
|
||||
// // reset to the item's id instead of the radiogroup id
|
||||
// radio.id = 'rb-' + this.registerInput('radio');
|
||||
// radio.labelId = 'lbl-' + this.itemId;
|
||||
// }
|
||||
|
||||
@Method()
|
||||
getLabelText(): string {
|
||||
return this.label ? this.label.getText() : '';
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.itemId = (++itemId).toString();
|
||||
if (hasChildStyleChange) {
|
||||
this.hasStyleChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
@ -89,34 +67,6 @@ export class Item {
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
buttons[i].itemButton = true;
|
||||
}
|
||||
|
||||
this.label = this.el.querySelector('ion-label');
|
||||
|
||||
// if (label) {
|
||||
// this.label = label;
|
||||
// this.labelId = label.id = ('lbl-' + this.itemId);
|
||||
// if (label.type) {
|
||||
// this.setElementClass('item-label-' + label.type, true);
|
||||
// }
|
||||
// this.viewLabel = false;
|
||||
// }
|
||||
|
||||
// if (this._viewLabel && this.inputs.length) {
|
||||
// let labelText = this.getLabelText().trim();
|
||||
// this._viewLabel = (labelText.length > 0);
|
||||
// }
|
||||
|
||||
// if (this.inputs.length > 1) {
|
||||
// this.setElementClass('item-multiple-inputs', true);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
registerInput(type: string) {
|
||||
this.inputs.push(type);
|
||||
return this.itemId + '-' + (++this.ids);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -132,6 +82,8 @@ export class Item {
|
||||
'item-block': true
|
||||
};
|
||||
|
||||
this.hasStyleChange = false;
|
||||
|
||||
// TODO add support for button items
|
||||
const TagType = this.href ? 'a' : 'div';
|
||||
|
||||
@ -149,58 +101,4 @@ export class Item {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// constructor() {
|
||||
// this._setName(elementRef);
|
||||
// this._hasReorder = !!reorder;
|
||||
// this.itemId = form.nextId().toString();
|
||||
|
||||
// // auto add "tappable" attribute to ion-item components that have a click listener
|
||||
// if (!(<any>renderer).orgListen) {
|
||||
// (<any>renderer).orgListen = renderer.listen;
|
||||
// renderer.listen = function(renderElement: HTMLElement, name: string, callback: Function): Function {
|
||||
// if (name === 'click' && renderElement.setAttribute) {
|
||||
// renderElement.setAttribute('tappable', '');
|
||||
// }
|
||||
// return (<any>renderer).orgListen(renderElement, name, callback);
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @hidden
|
||||
// */
|
||||
// @ContentChild(Label)
|
||||
// set contentLabel(label: Label) {
|
||||
// if (label) {
|
||||
// this._label = label;
|
||||
// this.labelId = label.id = ('lbl-' + this.itemId);
|
||||
// if (label.type) {
|
||||
// this.setElementClass('item-label-' + label.type, true);
|
||||
// }
|
||||
// this._viewLabel = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @hidden
|
||||
// */
|
||||
// @ViewChild(Label)
|
||||
// set viewLabel(label: Label) {
|
||||
// if (!this._label) {
|
||||
// this._label = label;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @hidden
|
||||
// */
|
||||
// @ContentChildren(Icon)
|
||||
// set _icons(icons: QueryList<Icon>) {
|
||||
// icons.forEach(icon => {
|
||||
// icon.setElementClass('item-icon', true);
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
var itemId = -1;
|
||||
|
||||
150
packages/core/src/components/radio-group/radio-group.tsx
Normal file
150
packages/core/src/components/radio-group/radio-group.tsx
Normal file
@ -0,0 +1,150 @@
|
||||
import { Component, ComponentDidLoad, Element, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
|
||||
import { HTMLIonRadioElementEvent } from '../radio/radio';
|
||||
import { RadioGroupInput, TextInputChangeEvent } from '../../utils/input-interfaces';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-radio-group'
|
||||
})
|
||||
export class RadioGroup implements ComponentDidLoad, RadioGroupInput {
|
||||
radios: HTMLIonRadioElement[] = [];
|
||||
|
||||
@Element() el: HTMLElement;
|
||||
|
||||
@State() labelId: string;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the radios can be deselected. Default false.
|
||||
*/
|
||||
@Prop() allowEmptySelection = false;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the radio group. Default false.
|
||||
*/
|
||||
@Prop({ mutable: true }) disabled = false;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Prop({ mutable: true }) name: string;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the radio group.
|
||||
*/
|
||||
@Prop({ mutable: true }) value: string;
|
||||
|
||||
@PropDidChange('value')
|
||||
valueChanged() {
|
||||
// this radio group's value just changed
|
||||
// double check the button with this value is checked
|
||||
if (this.value === undefined) {
|
||||
// set to undefined
|
||||
// ensure all that are checked become unchecked
|
||||
this.radios.filter(r => r.checked).forEach(radio => {
|
||||
radio.checked = false;
|
||||
});
|
||||
|
||||
} else {
|
||||
let hasChecked = false;
|
||||
|
||||
this.radios.forEach(radio => {
|
||||
if (radio.value === this.value) {
|
||||
if (!radio.checked && !hasChecked) {
|
||||
// correct value for this radio
|
||||
// but this radio isn't checked yet
|
||||
// and we haven't found a checked yet
|
||||
// so CHECK IT!
|
||||
radio.checked = true;
|
||||
|
||||
} else if (hasChecked && radio.checked) {
|
||||
// somehow we've got multiple radios
|
||||
// with the same value, but only one can be checked
|
||||
radio.checked = false;
|
||||
}
|
||||
|
||||
// remember we've got a checked radio button now
|
||||
hasChecked = true;
|
||||
|
||||
} else if (radio.checked) {
|
||||
// this radio doesn't have the correct value
|
||||
// and it's also checked, so let's uncheck it
|
||||
radio.checked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// emit the new value
|
||||
this.ionChange.emit({ value: this.value });
|
||||
}
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the value has changed.
|
||||
*/
|
||||
@Event() ionChange: EventEmitter<TextInputChangeEvent>;
|
||||
|
||||
@Listen('ionRadioDidLoad')
|
||||
onRadioDidLoad(ev: HTMLIonRadioElementEvent) {
|
||||
const radio = ev.target;
|
||||
this.radios.push(radio);
|
||||
radio.name = this.name;
|
||||
|
||||
if (radio.checked && !this.value) {
|
||||
// set the initial value from the check radio's value
|
||||
this.value = radio.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Listen('ionRadioDidUnload')
|
||||
onRadioDidUnload(ev: HTMLIonRadioElementEvent) {
|
||||
const index = this.radios.indexOf(ev.target);
|
||||
if (index > -1) {
|
||||
this.radios.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Listen('ionSelect')
|
||||
onRadioSelect(ev: HTMLIonRadioElementEvent) {
|
||||
// ionSelect only come from the checked radio button
|
||||
this.radios.forEach(radio => {
|
||||
if (radio === ev.target) {
|
||||
this.value = radio.value;
|
||||
} else {
|
||||
radio.checked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.name = this.name || 'ion-rg-' + (radioGroupIds++);
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
// Get the list header if it exists and set the id
|
||||
// this is used to set aria-labelledby
|
||||
let header = this.el.querySelector('ion-list-header');
|
||||
if (!header) {
|
||||
header = this.el.querySelector('ion-item-divider');
|
||||
}
|
||||
if (header) {
|
||||
const label = header.querySelector('ion-label');
|
||||
if (label) {
|
||||
this.labelId = label.id = this.name + '-lbl';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hostData() {
|
||||
const hostAttrs: any = {
|
||||
'role': 'radiogroup'
|
||||
};
|
||||
if (this.labelId) {
|
||||
hostAttrs['aria-labelledby'] = this.labelId;
|
||||
}
|
||||
return hostAttrs;
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>;
|
||||
}
|
||||
}
|
||||
|
||||
let radioGroupIds = 0;
|
||||
46
packages/core/src/components/radio-group/readme.md
Normal file
46
packages/core/src/components/radio-group/readme.md
Normal file
@ -0,0 +1,46 @@
|
||||
# ion-radio-group
|
||||
|
||||
A radio group is a group of [radio buttons](../radio). It allows
|
||||
a user to select at most one radio button from a set. Checking one radio
|
||||
button that belongs to a radio group unchecks any previous checked
|
||||
radio button within the same group.
|
||||
|
||||
|
||||
```html
|
||||
<ion-list>
|
||||
|
||||
<ion-radio-group>
|
||||
|
||||
<ion-list-header>
|
||||
Auto Manufacturers
|
||||
</ion-list-header>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Cord</ion-label>
|
||||
<ion-radio value="cord"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Duesenberg</ion-label>
|
||||
<ion-radio value="duesenberg"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Hudson</ion-label>
|
||||
<ion-radio value="hudson"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Packard</ion-label>
|
||||
<ion-radio value="packard"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Studebaker</ion-label>
|
||||
<ion-radio value="studebaker"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
</ion-radio-group>
|
||||
|
||||
</ion-list>
|
||||
```
|
||||
105
packages/core/src/components/radio-group/test/form/index.html
Normal file
105
packages/core/src/components/radio-group/test/form/index.html
Normal file
@ -0,0 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Radio Group - Form</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<script src="/dist/ionic.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-page>
|
||||
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Radio Group - Form</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="outer-content">
|
||||
<form>
|
||||
|
||||
<ion-list>
|
||||
|
||||
<ion-radio-group name="tannen" id="group">
|
||||
|
||||
<ion-list-header>
|
||||
<ion-label>Luckiest Man On Earth</ion-label>
|
||||
</ion-list-header>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Biff <span id="biff"></span></ion-label>
|
||||
<ion-radio value="biff" slot="start"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Griff <span id="griff"></span></ion-label>
|
||||
<ion-radio value="griff" slot="start"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Buford <span id="buford"></span></ion-label>
|
||||
<ion-radio value="buford" slot="start"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>George</ion-label>
|
||||
<ion-radio value="george" disabled slot="start"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-button type="submit">Submit</ion-button>
|
||||
</ion-item>
|
||||
|
||||
</ion-radio-group>
|
||||
|
||||
</ion-list>
|
||||
|
||||
</form>
|
||||
|
||||
<p style="margin: 20px">
|
||||
Value: <span id="value"></span>
|
||||
</p>
|
||||
|
||||
<p style="margin: 20px">
|
||||
Changes: <span id="changes">0</span>
|
||||
</p>
|
||||
|
||||
</ion-content>
|
||||
|
||||
</ion-page>
|
||||
|
||||
<script>
|
||||
var changes = 0;
|
||||
|
||||
document.getElementById('group').addEventListener('ionChange', function(ev) {
|
||||
document.getElementById('value').textContent = ev.detail.value;
|
||||
changes++;
|
||||
document.getElementById('changes').textContent = changes;
|
||||
});
|
||||
|
||||
var biff = 0;
|
||||
document.querySelector('[value="biff"]').addEventListener('ionSelect', function(ev) {
|
||||
biff++;
|
||||
document.getElementById('biff').textContent = biff;
|
||||
});
|
||||
|
||||
var griff = 0;
|
||||
document.querySelector('[value="griff"]').addEventListener('ionSelect', function(ev) {
|
||||
griff++;
|
||||
document.getElementById('griff').textContent = griff;
|
||||
});
|
||||
|
||||
var buford = 0;
|
||||
document.querySelector('[value="buford"]').addEventListener('ionSelect', function(ev) {
|
||||
buford++;
|
||||
document.getElementById('buford').textContent = buford;
|
||||
});
|
||||
</script>
|
||||
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
@ -1,183 +0,0 @@
|
||||
import { Component, Element, Event, EventEmitter, Listen, Prop, PropDidChange, State} from '@stencil/core';
|
||||
|
||||
import { isCheckedProperty } from '../../utils/helpers';
|
||||
|
||||
import { Radio, RadioEvent } from './radio';
|
||||
|
||||
|
||||
/**
|
||||
* @name RadioGroup
|
||||
* @description
|
||||
* A radio group is a group of [radio buttons](../RadioButton). It allows
|
||||
* a user to select at most one radio button from a set. Checking one radio
|
||||
* button that belongs to a radio group unchecks any previous checked
|
||||
* radio button within the same group.
|
||||
*
|
||||
* See the [Angular Forms Docs](https://angular.io/docs/ts/latest/guide/forms.html)
|
||||
* for more information on forms and inputs.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-list radio-group [(ngModel)]="autoManufacturers">
|
||||
*
|
||||
* <ion-list-header>
|
||||
* Auto Manufacturers
|
||||
* </ion-list-header>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Cord</ion-label>
|
||||
* <ion-radio value="cord"></ion-radio>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Duesenberg</ion-label>
|
||||
* <ion-radio value="duesenberg"></ion-radio>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Hudson</ion-label>
|
||||
* <ion-radio value="hudson"></ion-radio>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Packard</ion-label>
|
||||
* <ion-radio value="packard"></ion-radio>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Studebaker</ion-label>
|
||||
* <ion-radio value="studebaker"></ion-radio>
|
||||
* </ion-item>
|
||||
*
|
||||
* </ion-list>
|
||||
* ```
|
||||
*
|
||||
* @demo /docs/demos/src/radio/
|
||||
* @see {@link /docs/components#radio Radio Component Docs}
|
||||
* @see {@link ../RadioButton RadioButton API Docs}
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-radio-group'
|
||||
})
|
||||
export class RadioGroup {
|
||||
radios: Radio[] = [];
|
||||
radioGroupId: number;
|
||||
ids = 0;
|
||||
|
||||
@Element() private el: HTMLElement;
|
||||
|
||||
@State() activeId: string;
|
||||
@State() headerId: string;
|
||||
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the value has changed.
|
||||
*/
|
||||
@Event() ionChange: EventEmitter;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the radios can be deselected. Default false.
|
||||
*/
|
||||
@Prop() allowEmptySelection: boolean = false;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the radio group. Default false.
|
||||
*/
|
||||
@Prop({ mutable: true }) disabled: boolean = false;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the radio group.
|
||||
*/
|
||||
@Prop({ mutable: true }) value: string;
|
||||
|
||||
@PropDidChange('value')
|
||||
protected valueChanged() {
|
||||
this.update();
|
||||
this.ionChange.emit(this);
|
||||
}
|
||||
|
||||
@Listen('ionRadioDidLoad')
|
||||
protected radioDidLoad(ev: RadioEvent) {
|
||||
const radio = ev.detail.radio;
|
||||
this.radios.push(radio);
|
||||
radio.radioId = 'rb-' + this.radioGroupId + '-' + (++this.ids);
|
||||
|
||||
// if the value is not defined then use its unique id
|
||||
radio.value = !radio.value ? radio.radioId : radio.value;
|
||||
|
||||
if (radio.checked && !this.value) {
|
||||
this.value = radio.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Listen('ionRadioCheckedDidChange')
|
||||
protected radioCheckedDidChange(ev: RadioEvent) {
|
||||
const radio = ev.detail.radio;
|
||||
|
||||
// TODO shouldn't be able to set radio checked to false
|
||||
// if allowEmptySelection is false
|
||||
if (radio.checked && this.value !== radio.value) {
|
||||
this.value = radio.checked ? radio.value : '';
|
||||
}
|
||||
}
|
||||
|
||||
@Listen('ionRadioDidToggle')
|
||||
protected radioDidToggle(ev: RadioEvent) {
|
||||
const radio = ev.detail.radio;
|
||||
|
||||
// If the group does not allow empty selection then checked
|
||||
// should be true, otherwise leave it as is
|
||||
radio.checked = this.allowEmptySelection ? radio.checked : true;
|
||||
this.value = radio.checked ? radio.value : '';
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.radioGroupId = ++radioGroupIds;
|
||||
|
||||
// Get the list header if it exists and set the id
|
||||
const header = this.el.querySelector('ion-list-header');
|
||||
|
||||
if (header) {
|
||||
if (!header.id) {
|
||||
header.id = 'rg-hdr-' + this.radioGroupId;
|
||||
}
|
||||
this.headerId = header.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
update() {
|
||||
// loop through each of the radios
|
||||
let hasChecked = false;
|
||||
this.radios.forEach((radio: Radio) => {
|
||||
|
||||
// Check the radio if the value is the same as the group value
|
||||
radio.checked = isCheckedProperty(this.value, radio.value) && !hasChecked;
|
||||
|
||||
if (radio.checked) {
|
||||
// if this button is checked, then set it as
|
||||
// the radiogroup's active descendant
|
||||
this.activeId = radio.radioId;
|
||||
hasChecked = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
'role': 'radiogroup',
|
||||
'aria-activedescendant': this.activeId,
|
||||
'aria-describedby': this.headerId
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>;
|
||||
}
|
||||
}
|
||||
|
||||
let radioGroupIds = -1;
|
||||
@ -9,7 +9,7 @@ ion-radio {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.radio-cover {
|
||||
ion-radio input {
|
||||
@include position(0, null, null, 0);
|
||||
|
||||
position: absolute;
|
||||
@ -19,4 +19,28 @@ ion-radio {
|
||||
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.radio-outline {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.radio-key .radio-outline {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 10px;
|
||||
|
||||
display: block;
|
||||
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
|
||||
background: #86A8DF;
|
||||
opacity: .3;
|
||||
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@ -1,43 +1,8 @@
|
||||
import { Component, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
|
||||
|
||||
import { BlurEvent, CheckedInputChangeEvent, FocusEvent, RadioButtonInput, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { Component, ComponentDidLoad, ComponentDidUnload, ComponentWillLoad, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A radio button is a button that can be either checked or unchecked. A user can tap
|
||||
* the button to check or uncheck it. It can also be checked from the template using
|
||||
* the `checked` property.
|
||||
*
|
||||
* Use an element with a `radio-group` attribute to group a set of radio buttons. When
|
||||
* radio buttons are inside a [radio group](../RadioGroup), exactly one radio button
|
||||
* in the group can be checked at any time. If a radio button is not placed in a group,
|
||||
* they will all have the ability to be checked at the same time.
|
||||
*
|
||||
* See the [Angular Forms Docs](https://angular.io/docs/ts/latest/guide/forms.html) for
|
||||
* more information on forms and input.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-list radio-group [(ngModel)]="relationship">
|
||||
* <ion-item>
|
||||
* <ion-label>Friends</ion-label>
|
||||
* <ion-radio value="friends" checked></ion-radio>
|
||||
* </ion-item>
|
||||
* <ion-item>
|
||||
* <ion-label>Family</ion-label>
|
||||
* <ion-radio value="family"></ion-radio>
|
||||
* </ion-item>
|
||||
* <ion-item>
|
||||
* <ion-label>Enemies</ion-label>
|
||||
* <ion-radio value="enemies" [disabled]="isDisabled"></ion-radio>
|
||||
* </ion-item>
|
||||
* </ion-list>
|
||||
* ```
|
||||
* @demo /docs/demos/src/radio/
|
||||
* @see {@link /docs/components#radio Radio Component Docs}
|
||||
* @see {@link ../RadioGroup RadioGroup API Docs}
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-radio',
|
||||
styleUrls: {
|
||||
@ -48,13 +13,14 @@ import { createThemedClasses } from '../../utils/theme';
|
||||
theme: 'radio'
|
||||
}
|
||||
})
|
||||
export class Radio {
|
||||
labelId: string;
|
||||
export class Radio implements RadioButtonInput, ComponentDidLoad, ComponentDidUnload, ComponentWillLoad {
|
||||
didLoad: boolean;
|
||||
inputId: string;
|
||||
nativeInput: HTMLInputElement;
|
||||
styleTmr: any;
|
||||
|
||||
@State() radioId: string;
|
||||
|
||||
@State() activated: boolean;
|
||||
@State() keyFocus: boolean;
|
||||
|
||||
/**
|
||||
* @output {RadioEvent} Emitted when the radio loads.
|
||||
@ -66,25 +32,25 @@ export class Radio {
|
||||
*/
|
||||
@Event() ionRadioDidUnload: EventEmitter;
|
||||
|
||||
/**
|
||||
* @output {RadioEvent} Emitted when the radio is toggled.
|
||||
*/
|
||||
@Event() ionRadioDidToggle: EventEmitter;
|
||||
|
||||
/**
|
||||
* @output {RadioEvent} Emitted when the radio checked property is changed.
|
||||
*/
|
||||
@Event() ionRadioCheckedDidChange: EventEmitter;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the styles change.
|
||||
*/
|
||||
@Event() ionStyle: EventEmitter;
|
||||
@Event() ionStyle: EventEmitter<StyleEvent>;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the radio is selected.
|
||||
* @output {Event} Emitted when the radio button is selected.
|
||||
*/
|
||||
@Event() ionSelect: EventEmitter;
|
||||
@Event() ionSelect: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the radio button has focus.
|
||||
*/
|
||||
@Event() ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the radio button loses focus.
|
||||
*/
|
||||
@Event() ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
@ -101,26 +67,46 @@ export class Radio {
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, the radio is selected. Defaults to `false`.
|
||||
*/
|
||||
@Prop({ mutable: true }) checked: boolean = false;
|
||||
@Prop() name: string;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the radio. Default false.
|
||||
*/
|
||||
@Prop({ mutable: true }) disabled: boolean = false;
|
||||
@Prop() disabled = false;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, the radio is selected. Defaults to `false`.
|
||||
*/
|
||||
@Prop({ mutable: true }) checked = false;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the radio.
|
||||
*/
|
||||
@Prop({ mutable: true }) value: string;
|
||||
|
||||
|
||||
componentWillLoad() {
|
||||
this.inputId = 'ion-rb-' + (radioButtonIds++);
|
||||
if (this.value === undefined) {
|
||||
this.value = this.inputId;
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.ionRadioDidLoad.emit({ radio: this });
|
||||
this.nativeInput.checked = this.checked;
|
||||
this.didLoad = true;
|
||||
|
||||
const parentItem = this.nativeInput.closest('ion-item');
|
||||
if (parentItem) {
|
||||
const itemLabel = parentItem.querySelector('ion-label');
|
||||
if (itemLabel) {
|
||||
itemLabel.id = this.inputId + '-lbl';
|
||||
this.nativeInput.setAttribute('aria-labelledby', itemLabel.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
@ -128,53 +114,79 @@ export class Radio {
|
||||
}
|
||||
|
||||
@PropDidChange('color')
|
||||
protected colorChanged() {
|
||||
colorChanged() {
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@PropDidChange('checked')
|
||||
protected checkedChanged(val: boolean) {
|
||||
this.ionRadioCheckedDidChange.emit({ radio: this });
|
||||
this.ionSelect.emit({ checked: val });
|
||||
checkedChanged(isChecked: boolean) {
|
||||
if (this.nativeInput.checked !== isChecked) {
|
||||
// keep the checked value and native input `nync
|
||||
this.nativeInput.checked = isChecked;
|
||||
}
|
||||
if (this.didLoad && isChecked) {
|
||||
// only emit ionSelect when checked is true
|
||||
this.ionSelect.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@PropDidChange('disabled')
|
||||
protected disabledChanged() {
|
||||
disabledChanged(val: boolean) {
|
||||
this.nativeInput.disabled = val;
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
private emitStyle() {
|
||||
emitStyle() {
|
||||
clearTimeout(this.styleTmr);
|
||||
|
||||
this.styleTmr = setTimeout(() => {
|
||||
this.ionStyle.emit({
|
||||
...createThemedClasses(this.mode, this.color, 'radio'),
|
||||
'radio-checked': this.checked,
|
||||
'radio-disabled': this.disabled,
|
||||
'radio-disabled': this.disabled
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Listen('keydown.space')
|
||||
onSpace(ev: KeyboardEvent) {
|
||||
this.toggle();
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
onChange() {
|
||||
this.onClick();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.checked = !this.checked;
|
||||
this.ionRadioDidToggle.emit({ radio: this });
|
||||
onKeyUp() {
|
||||
this.keyFocus = true;
|
||||
}
|
||||
|
||||
onFocus() {
|
||||
this.ionFocus.emit();
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
this.keyFocus = false;
|
||||
this.ionBlur.emit();
|
||||
}
|
||||
|
||||
@Listen('click')
|
||||
onClick() {
|
||||
if (!this.checked && !this.disabled) {
|
||||
this.checked = true;
|
||||
this.nativeInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
const hostAttrs: any = {
|
||||
'class': {
|
||||
'radio-checked': this.checked,
|
||||
'radio-disabled': this.disabled
|
||||
'radio-disabled': this.disabled,
|
||||
'radio-key': this.keyFocus
|
||||
}
|
||||
};
|
||||
|
||||
return hostAttrs;
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -182,27 +194,29 @@ export class Radio {
|
||||
'radio-icon': true,
|
||||
'radio-checked': this.checked
|
||||
};
|
||||
|
||||
return [
|
||||
<div class={radioClasses}>
|
||||
<div class='radio-inner'></div>
|
||||
<div class='radio-inner'/>
|
||||
</div>,
|
||||
<button
|
||||
class='radio-cover'
|
||||
onClick={() => this.toggle()}
|
||||
id={this.radioId}
|
||||
aria-checked={this.checked ? 'true' : false}
|
||||
aria-disabled={this.disabled ? 'true' : false}
|
||||
aria-labelledby={this.labelId}
|
||||
role='radio'
|
||||
tabIndex={0}
|
||||
/>
|
||||
<div class='radio-outline'/>,
|
||||
<input
|
||||
type='radio'
|
||||
onChange={this.onChange.bind(this)}
|
||||
onFocus={this.onFocus.bind(this)}
|
||||
onBlur={this.onBlur.bind(this)}
|
||||
onKeyUp={this.onKeyUp.bind(this)}
|
||||
id={this.inputId}
|
||||
name={this.name}
|
||||
value={this.value}
|
||||
disabled={this.disabled}
|
||||
ref={r => this.nativeInput = (r as any)}/>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export interface RadioEvent extends Event {
|
||||
detail: {
|
||||
radio: Radio;
|
||||
};
|
||||
|
||||
export interface HTMLIonRadioElementEvent extends CustomEvent {
|
||||
target: HTMLIonRadioElement;
|
||||
}
|
||||
|
||||
let radioButtonIds = 0;
|
||||
|
||||
40
packages/core/src/components/radio/readme.md
Normal file
40
packages/core/src/components/radio/readme.md
Normal file
@ -0,0 +1,40 @@
|
||||
# ion-radio
|
||||
|
||||
A radio button is a button that can be either checked or unchecked. A user can tap
|
||||
the button to check or uncheck it. It can also be checked programmatically by changing
|
||||
the `checked` property or `checked` attribute.
|
||||
|
||||
Use an `ion-radio-group` component to group a set of radio buttons. When
|
||||
radio buttons are inside a [radio group](../radio-group), only one radio button
|
||||
in the group can be checked at any time. If a radio button is not placed in a group,
|
||||
then they will all have the ability to be checked at the same time.
|
||||
|
||||
|
||||
```html
|
||||
<ion-list>
|
||||
|
||||
<ion-radio-group>
|
||||
|
||||
<ion-list-header>
|
||||
Name
|
||||
</ion-list-header>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Biff</ion-label>
|
||||
<ion-radio value="biff" checked></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Griff</ion-label>
|
||||
<ion-radio value="griff"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Buford</ion-label>
|
||||
<ion-radio value="buford"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
</ion-radio-group>
|
||||
|
||||
</ion-list>
|
||||
```
|
||||
@ -1,4 +1,4 @@
|
||||
import { BlurEvent, BooleanInput, BooleanInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { BlurEvent, CheckboxInput, CheckedInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { Component, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
|
||||
import { GestureDetail } from '../../index';
|
||||
import { hapticSelection } from '../../utils/haptic';
|
||||
@ -14,7 +14,7 @@ import { hapticSelection } from '../../utils/haptic';
|
||||
theme: 'toggle'
|
||||
}
|
||||
})
|
||||
export class Toggle implements BooleanInput {
|
||||
export class Toggle implements CheckboxInput {
|
||||
private toggleId: string;
|
||||
private labelId: string;
|
||||
private styleTmr: any;
|
||||
@ -27,7 +27,7 @@ export class Toggle implements BooleanInput {
|
||||
/**
|
||||
* @output {Event} Emitted when the value property has changed.
|
||||
*/
|
||||
@Event() ionChange: EventEmitter<BooleanInputChangeEvent>;
|
||||
@Event() ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the styles change.
|
||||
@ -64,8 +64,11 @@ export class Toggle implements BooleanInput {
|
||||
@Prop({ mutable: true }) checked: boolean = false;
|
||||
|
||||
@PropDidChange('checked')
|
||||
protected checkedChanged(val: boolean) {
|
||||
this.ionChange.emit({ checked: val });
|
||||
checkedChanged(isChecked: boolean) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@ -75,7 +78,7 @@ export class Toggle implements BooleanInput {
|
||||
@Prop({ mutable: true }) disabled: boolean = false;
|
||||
|
||||
@PropDidChange('disabled')
|
||||
protected disabledChanged() {
|
||||
disabledChanged() {
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
|
||||
4
packages/core/src/index.d.ts
vendored
4
packages/core/src/index.d.ts
vendored
@ -117,8 +117,8 @@ export {
|
||||
iOSLeaveAnimation as PopoverIOSLeaveAnimation
|
||||
} from './components/popover/popover';
|
||||
export { PopoverController } from './components/popover-controller/popover-controller';
|
||||
export { RadioGroup } from './components/radio/radio-group';
|
||||
export { Radio, RadioEvent } from './components/radio/radio';
|
||||
export { RadioGroup } from './components/radio-group/radio-group';
|
||||
export { Radio, HTMLIonRadioElementEvent } from './components/radio/radio';
|
||||
export { RangeKnob } from './components/range/range-knob';
|
||||
export { Range, RangeEvent } from './components/range/range';
|
||||
export { ReorderGroup } from './components/reorder/reorder-group';
|
||||
|
||||
131
packages/core/src/utils/input-interfaces.d.ts
vendored
131
packages/core/src/utils/input-interfaces.d.ts
vendored
@ -3,9 +3,6 @@ import { EventEmitter } from '@stencil/core';
|
||||
|
||||
export interface BaseInput {
|
||||
|
||||
// Properties
|
||||
// ------------------------
|
||||
|
||||
/**
|
||||
* Indicates that the user cannot interact with the control.
|
||||
*/
|
||||
@ -24,9 +21,19 @@ export interface BaseInput {
|
||||
*/
|
||||
value: string;
|
||||
|
||||
}
|
||||
|
||||
// Events
|
||||
// ------------------------
|
||||
|
||||
export interface CheckboxInput extends BaseInput {
|
||||
/**
|
||||
* Returns / Sets the current state of the element when type is checkbox or radio.
|
||||
*/
|
||||
checked: boolean;
|
||||
|
||||
/**
|
||||
* The change event is fired when the value of has changed.
|
||||
*/
|
||||
ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
@ -45,27 +52,50 @@ export interface BaseInput {
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export interface BooleanInput extends BaseInput {
|
||||
export interface RadioButtonInput extends BaseInput {
|
||||
/**
|
||||
* Returns / Sets the current state of the element when type is checkbox or radio.
|
||||
*/
|
||||
checked: boolean;
|
||||
|
||||
/**
|
||||
* The change event is fired when the value of has changed.
|
||||
* This is actually more similar to the native "input" event
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Events/input
|
||||
* A single radio button fires an ionSelect event, whereas
|
||||
* a radio group fires an ionChange event. It would be more common
|
||||
* to attach listeners to the radio group, not individual radio buttons.
|
||||
*/
|
||||
ionChange: EventEmitter<BooleanInputChangeEvent>;
|
||||
ionSelect: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
*/
|
||||
ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Focus on the input element; keystrokes will subsequently go to this element.
|
||||
*/
|
||||
ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change. This is useful for parent
|
||||
* components to know how to style themselves depending on the
|
||||
* child input. For example, a disabled ion-toggle may give
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
}
|
||||
|
||||
|
||||
export interface BooleanInputChangeEvent {
|
||||
export interface CheckedInputChangeEvent {
|
||||
checked: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
|
||||
export interface TextInputChangeEvent {
|
||||
value: string;
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +104,6 @@ export interface SelectOptionInput extends BaseInput {
|
||||
* Indicates whether the option is currently selected.
|
||||
*/
|
||||
selected: boolean;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -95,18 +124,92 @@ export interface SelectInput extends BaseInput {
|
||||
* whether multiple items can be selected.
|
||||
*/
|
||||
multiple: boolean;
|
||||
|
||||
/**
|
||||
* The change event is fired when the value of has changed.
|
||||
* This is actually more similar to the native "input" event
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Events/input
|
||||
*/
|
||||
ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
*/
|
||||
ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Focus on the input element; keystrokes will subsequently go to this element.
|
||||
*/
|
||||
ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change. This is useful for parent
|
||||
* components to know how to style themselves depending on the
|
||||
* child input. For example, a disabled ion-toggle may give
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
}
|
||||
|
||||
|
||||
export interface RadioGroupInput extends BaseInput {
|
||||
ionChange: EventEmitter<TextInputChangeEvent>;
|
||||
}
|
||||
|
||||
|
||||
export interface TextInput extends BaseInput {
|
||||
/**
|
||||
*
|
||||
* The change event is fired when the value of has changed.
|
||||
* This is actually more similar to the native "input" event
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Events/input
|
||||
*/
|
||||
ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
*/
|
||||
ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Focus on the input element; keystrokes will subsequently go to this element.
|
||||
*/
|
||||
ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change. This is useful for parent
|
||||
* components to know how to style themselves depending on the
|
||||
* child input. For example, a disabled ion-toggle may give
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
}
|
||||
|
||||
|
||||
export interface TextMultiLineInput extends TextInput {
|
||||
/**
|
||||
* The change event is fired when the value of has changed.
|
||||
* This is actually more similar to the native "input" event
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Events/input
|
||||
*/
|
||||
ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
*/
|
||||
ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Focus on the input element; keystrokes will subsequently go to this element.
|
||||
*/
|
||||
ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change. This is useful for parent
|
||||
* components to know how to style themselves depending on the
|
||||
* child input. For example, a disabled ion-toggle may give
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,122 +0,0 @@
|
||||
import { EventEmitter } from '@stencil/core';
|
||||
|
||||
|
||||
export interface BaseInput {
|
||||
|
||||
// Properties
|
||||
// ------------------------
|
||||
|
||||
/**
|
||||
* Indicates that the user cannot interact with the control.
|
||||
*/
|
||||
disabled: boolean;
|
||||
|
||||
/**
|
||||
* Returns / Sets the element's readonly attribute, indicating that
|
||||
* the user cannot modify the value of the control. HTML5. This is
|
||||
* ignored if the value of the type attribute is hidden, range, color,
|
||||
* checkbox, radio, file, or a button type.
|
||||
*/
|
||||
readOnly?: boolean;
|
||||
|
||||
/**
|
||||
* Reflects the value of the form control.
|
||||
*/
|
||||
value: string;
|
||||
|
||||
|
||||
// Events
|
||||
// ------------------------
|
||||
|
||||
/**
|
||||
* Removes focus from input; keystrokes will subsequently go nowhere.
|
||||
*/
|
||||
ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Focus on the input element; keystrokes will subsequently go to this element.
|
||||
*/
|
||||
ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change. This is useful for parent
|
||||
* components to know how to style themselves depending on the
|
||||
* child input. For example, a disabled ion-toggle may give
|
||||
* its wrapping ion-item a different style.
|
||||
*/
|
||||
ionStyle: EventEmitter<StyleEvent>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export interface BooleanInput extends BaseInput {
|
||||
/**
|
||||
* Returns / Sets the current state of the element when type is checkbox or radio.
|
||||
*/
|
||||
checked: boolean;
|
||||
|
||||
/**
|
||||
* The change event is fired when the value of has changed.
|
||||
* This is actually more similar to the native "input" event
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Events/input
|
||||
*/
|
||||
ionChange: EventEmitter<BooleanInputChangeEvent>;
|
||||
}
|
||||
|
||||
|
||||
export interface BooleanInputChangeEvent {
|
||||
checked: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface SelectOptionInput extends BaseInput {
|
||||
/**
|
||||
* Indicates whether the option is currently selected.
|
||||
*/
|
||||
selected: boolean;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export interface SelectInput extends BaseInput {
|
||||
/**
|
||||
* Indicates whether the option is currently selected.
|
||||
*/
|
||||
selected: boolean;
|
||||
|
||||
/**
|
||||
* A long reflecting the index of the first selected <option> element.
|
||||
* The value -1 indicates no element is selected.
|
||||
*/
|
||||
selectedIndex: number;
|
||||
|
||||
/**
|
||||
* Reflecting the multiple HTML attribute, which indicates
|
||||
* whether multiple items can be selected.
|
||||
*/
|
||||
multiple: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface TextInput extends BaseInput {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
export interface TextMultiLineInput extends TextInput {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export interface StyleEvent {
|
||||
[styleName: string]: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface FocusEvent {}
|
||||
|
||||
|
||||
export interface BlurEvent {}
|
||||
|
||||
Reference in New Issue
Block a user