feat(radio): add radio and radio group component

This commit is contained in:
Brandy Carney
2017-09-01 18:47:56 -04:00
parent 374bdd3668
commit f1ac5304d6
10 changed files with 1083 additions and 0 deletions

View File

@ -12,6 +12,9 @@ import { createThemedClasses } from '../../utils/theme';
}
})
export class Item {
private ids: number = -1;
private id: string;
private childStyles: CssClassMap = Object.create(null);
private label: any;
@ -63,6 +66,15 @@ export class Item {
// }
}
/**
* @hidden
*/
@Method()
registerInput(type: string) {
// this.inputs.push(type);
return this.id + '-' + (++this.ids);
}
render() {
let themedClasses = {
...this.childStyles,

View File

@ -0,0 +1,159 @@
import { Component, Element, Event, EventEmitter, HostElement, Prop , State} from '@stencil/core';
import { Radio } from './radio';
import { isCheckedProperty } from '../../utils/helpers';
/**
* @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[];
@Element() el: HTMLElement;
@State() activeId: string;
@State() headerId: string;
/**
* @output {any} Emitted when the selected button 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 this element. Default false.
*/
@Prop({ state: true }) disabled: boolean = false;
/**
* @input {string} the value of the radio.
*/
@Prop({ state: true }) value: string;
ionViewWillLoad() {
let radioGroupId = ++radioGroupIds;
let radioId = 0;
const radios = this.el.querySelectorAll('ion-radio') as NodeListOf<HostElement>;
for (var i = 0; i < radios.length; i++) {
const radio = radios[i].$instance;
if (radio) {
radio.id = 'rb-' + radioGroupId + '-' + (++radioId);
if (radio.checked) {
this.activeId = radio.id;
}
} else {
}
}
// Get the list header if it exists and set the id
const header = this.el.querySelector('ion-list-header') as HostElement;
if (header) {
if (!header.id) {
header.id = 'rg-hdr-' + radioGroupId;
}
this.headerId = header.id;
}
}
/**
* @hidden
*/
update() {
// loop through each of the radios
let hasChecked = false;
this.radios.forEach(radio => {
// check this radiobutton if its value is
// the same as the radiogroups 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.id;
hasChecked = true;
}
});
}
hostData() {
return {
attrs: {
'role': 'radiogroup',
'aria-activedescendant': this.activeId,
'aria-describedby': this.headerId
}
};
}
render() {
return <slot></slot>;
}
}
let radioGroupIds = -1;

View File

@ -0,0 +1,156 @@
@import "../../themes/ionic.globals.ios";
@import "./radio";
// iOS Radio
// --------------------------------------------------
/// @prop - Color of the checked radio
$radio-ios-color-on: color($colors-ios, primary) !default;
/// @prop - Width of the radio icon
$radio-ios-icon-width: 16px !default;
/// @prop - Height of the radio icon
$radio-ios-icon-height: 21px !default;
/// @prop - Border width of the radio icon
$radio-ios-icon-border-width: 2px !default;
/// @prop - Border style of the radio icon
$radio-ios-icon-border-style: solid !default;
/// @prop - Opacity of the disabled radio
$radio-ios-disabled-opacity: .3 !default;
// deprecated
$radio-ios-item-left-margin: null !default;
/// @prop - Margin top of the item-start in a radio
$radio-ios-item-start-margin-top: 8px !default;
/// @prop - Margin end of the item-start in a radio
$radio-ios-item-start-margin-end: 21px !default;
/// @prop - Margin bottom of the item-start in a radio
$radio-ios-item-start-margin-bottom: 8px !default;
/// @prop - Margin start of the item-start in a radio
$radio-ios-item-start-margin-start: 3px !default;
// deprecated
$radio-ios-item-right-margin: null !default;
/// @prop - Margin top of the item-end in a radio
$radio-ios-item-end-margin-top: $item-ios-padding-media-top !default;
/// @prop - Margin end of the item-end in a radio
$radio-ios-item-end-margin-end: 11px !default;
/// @prop - Margin bottom of the item-end in a radio
$radio-ios-item-end-margin-bottom: $item-ios-padding-media-bottom !default;
/// @prop - Margin start of the item-end in a radio
$radio-ios-item-end-margin-start: ($item-ios-padding-start / 2) !default;
// iOS Radio Circle: Unchecked
// -----------------------------------------
.radio-ios .radio-icon {
position: relative;
display: block;
width: $radio-ios-icon-width;
height: $radio-ios-icon-height;
}
// iOS Radio Checkmark: Checked
// -----------------------------------------
.radio-ios .radio-checked .radio-inner {
@include position(4px, null, null, 7px);
position: absolute;
width: 5px;
height: 12px;
border-width: $radio-ios-icon-border-width;
border-top-width: 0;
border-left-width: 0;
border-style: $radio-ios-icon-border-style;
border-color: $radio-ios-color-on;
transform: rotate(45deg);
}
// iOS Radio: Disabled
// -----------------------------------------
.radio-ios.radio-disabled,
.item-ios.item-radio-disabled ion-label {
opacity: $radio-ios-disabled-opacity;
pointer-events: none;
}
// iOS Radio Within An Item
// -----------------------------------------
.item-ios .radio-ios {
position: static;
display: block;
@include deprecated-variable(margin, $radio-ios-item-right-margin) {
@include margin($radio-ios-item-end-margin-top, $radio-ios-item-end-margin-end, $radio-ios-item-end-margin-bottom, $radio-ios-item-end-margin-start);
}
&[item-left], // deprecated
&[item-start] {
@include deprecated-variable(margin, $radio-ios-item-left-margin) {
@include margin($radio-ios-item-start-margin-top, $radio-ios-item-start-margin-end, $radio-ios-item-start-margin-bottom, $radio-ios-item-start-margin-start);
}
}
}
.item-radio.item-ios ion-label {
@include margin-horizontal(0, null);
}
// iOS Radio Item Label: Checked
// -----------------------------------------
.item-radio-checked.item-ios ion-label {
color: $radio-ios-color-on;
}
// iOS Radio Color Mixin
// --------------------------------------------------
@mixin radio-theme-ios($color-name, $color-base) {
.item-radio-ios-#{$color-name}.item-radio-checked ion-label {
color: $color-base;
}
.radio-ios-#{$color-name} .radio-checked {
color: $color-base;
}
.radio-ios-#{$color-name} .radio-checked .radio-inner {
border-color: $color-base;
}
}
// Generate iOS Radio Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-ios) {
@include radio-theme-ios($color-name, $color-base);
}

View File

@ -0,0 +1,190 @@
@import "../../themes/ionic.globals.md";
@import "./radio";
// Material Design Radio
// --------------------------------------------------
/// @prop - Color of the checked radio
$radio-md-color-on: color($colors-md, primary) !default;
/// @prop - Color of the unchecked radio
$radio-md-color-off: darken($list-md-border-color, 40%) !default;
/// @prop - Width of the radio icon
$radio-md-icon-width: 16px !default;
/// @prop - Height of the radio icon
$radio-md-icon-height: 16px !default;
/// @prop - Border width of the radio icon
$radio-md-icon-border-width: 2px !default;
/// @prop - Border style of the radio icon
$radio-md-icon-border-style: solid !default;
/// @prop - Border radius of the radio icon
$radio-md-icon-border-radius: 50% !default;
/// @prop - Transition duration of the radio
$radio-md-transition-duration: 280ms !default;
/// @prop - Transition easing of the radio
$radio-md-transition-easing: cubic-bezier(.4, 0, .2, 1) !default;
/// @prop - Opacity of the disabled radio
$radio-md-disabled-opacity: .3 !default;
// deprecated
$radio-md-item-left-margin: null !default;
/// @prop - Margin top of the item-start in a radio
$radio-md-item-start-margin-top: 11px !default;
/// @prop - Margin end of the item-start in a radio
$radio-md-item-start-margin-end: 36px !default;
/// @prop - Margin bottom of the item-start in a radio
$radio-md-item-start-margin-bottom: 10px !default;
/// @prop - Margin start of the item-start in a radio
$radio-md-item-start-margin-start: 4px !default;
// deprecated
$radio-md-item-right-margin: null !default;
/// @prop - Margin top of the item-end in a radio
$radio-md-item-end-margin-top: $item-md-padding-media-top !default;
/// @prop - Margin end of the item-end in a radio
$radio-md-item-end-margin-end: 10px !default;
/// @prop - Margin bottom of the item-end in a radio
$radio-md-item-end-margin-bottom: $item-md-padding-media-bottom !default;
/// @prop - Margin start of the item-end in a radio
$radio-md-item-end-margin-start: 0 !default;
// Material Design Radio Outer Circle: Unchecked
// -----------------------------------------
.radio-md .radio-icon {
@include position(0, null, null, 0);
@include margin(0);
@include border-radius($radio-md-icon-border-radius);
position: relative;
display: block;
width: $radio-md-icon-width;
height: $radio-md-icon-height;
border-width: $radio-md-icon-border-width;
border-style: $radio-md-icon-border-style;
border-color: $radio-md-color-off;
}
// Material Design Radio Inner Circle: Unchecked
// -----------------------------------------
.radio-md .radio-inner {
@include position($radio-md-icon-border-width, null, null, $radio-md-icon-border-width);
@include border-radius(50%);
position: absolute;
width: $radio-md-icon-width - $radio-md-icon-border-width * 4;
height: $radio-md-icon-height - $radio-md-icon-border-width * 4;
background-color: $radio-md-color-on;
transform: scale3d(0, 0, 0);
transition: transform $radio-md-transition-duration $radio-md-transition-easing;
}
// Material Design Radio Outer Circle: Checked
// -----------------------------------------
.radio-md .radio-checked {
border-color: $radio-md-color-on;
}
// Material Design Radio Inner Circle: Checked
// -----------------------------------------
.radio-md .radio-checked .radio-inner {
transform: scale3d(1, 1, 1);
}
// Material Design Radio: Disabled
// -----------------------------------------
.radio-md.radio-disabled,
.item-md.item-radio-disabled ion-label {
opacity: $radio-md-disabled-opacity;
pointer-events: none;
}
// Material Design Radio Within An Item
// -----------------------------------------
.item-md .radio-md {
position: static;
display: block;
@include deprecated-variable(margin, $radio-md-item-right-margin) {
@include margin($radio-md-item-end-margin-top, $radio-md-item-end-margin-end, $radio-md-item-end-margin-bottom, $radio-md-item-end-margin-start);
}
&[item-left], // deprecated
&[item-start] {
@include deprecated-variable(margin, $radio-md-item-left-margin) {
@include margin($radio-md-item-start-margin-top, $radio-md-item-start-margin-end, $radio-md-item-start-margin-bottom, $radio-md-item-start-margin-start);
}
}
}
.item-radio.item-md ion-label {
@include margin-horizontal(0, null);
}
// Material Design Radio Item Label: Checked
// -----------------------------------------
.item-radio-checked.item-md ion-label {
color: $radio-md-color-on;
}
// Material Design Radio Color Mixin
// --------------------------------------------------
@mixin radio-theme-md($color-name, $color-base, $color-contrast) {
.item-radio-md-#{$color-name}.item-radio-checked ion-label {
color: $color-base;
}
.radio-md-#{$color-name} .radio-checked {
border-color: $color-base;
}
.radio-md-#{$color-name} .radio-inner {
background-color: $color-base;
}
}
// Generate Material Design Radio Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-md) {
@include radio-theme-md($color-name, $color-base, $color-contrast);
}

View File

@ -0,0 +1,22 @@
@import "../../themes/ionic.globals";
// Radio
// --------------------------------------------------
ion-radio {
position: relative;
display: inline-block;
}
.radio-cover {
@include position(0, null, null, 0);
position: absolute;
width: 100%;
height: 100%;
background: transparent;
cursor: pointer;
}

View File

@ -0,0 +1,211 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
import { createThemedClasses } from '../../utils/theme';
import { RadioGroup } from './radio-group';
/**
* @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: {
ios: 'radio.ios.scss',
md: 'radio.md.scss',
wp: 'radio.wp.scss'
},
host: {
theme: 'radio'
}
})
export class Radio {
mode: string;
color: string;
group: any;
labelId: string;
styleTmr: any;
@Element() el: HTMLElement;
@State() id: string;
@State() activated: boolean;
/**
* @output {EventEmitter} Emitted when the styles of the radio change.
*/
@Event() ionStyle: EventEmitter;
/**
* @output {EventEmitter} Emitted when the radio is selected.
*/
@Event() ionSelect: EventEmitter;
/*
* @input {boolean} If true, the radio is checked. Default false.
*/
@Prop({ state: true }) checked: boolean = false;
/*
* @input {boolean} If true, the user cannot interact with this element. Default false.
*/
@Prop({ state: true }) disabled: boolean = false;
/**
* @input {string} the value of the radio.
*/
@Prop({ state: true }) value: string;
ionViewWillLoad() {
this.emitStyle();
}
ionViewDidLoad() {
this.group = this.el.closest('ion-radio-group') as any;
const item = this.el.closest('ion-item') as any;
if (item) {
// register the input inside of the item
// reset to the item's id instead of the radiogroup id
this.id = 'rb-' + item.registerInput('radio');
this.labelId = 'lbl-' + item.id;
}
// if the value is not defined then use it's unique id
this.value = !this.value ? this.id : this.value;
}
@PropDidChange('checked')
checkedChanged(val: boolean) {
this.ionSelect.emit({ checked: val });
if (this.group) {
this.group.value = this.value;
this.group.$instance.ionChange.emit(this);
}
this.emitStyle();
}
@PropDidChange('disabled')
disabledChanged() {
this.emitStyle();
}
private emitStyle() {
clearTimeout(this.styleTmr);
this.styleTmr = setTimeout(() => {
this.ionStyle.emit({
...createThemedClasses(this.mode, this.color, 'radio'),
'radio-checked': this.checked,
'radio-disabled': this.disabled,
});
});
}
@Listen('keydown.space')
onSpace(ev: KeyboardEvent) {
this.toggle();
ev.stopPropagation();
ev.preventDefault();
}
toggle() {
this.checked = !this.checked;
}
hostData() {
return {
class: {
'radio-checked': this.checked,
'radio-disabled': this.disabled
}
};
}
render() {
const radioClasses: CssClassMap = {
'radio-icon': true,
'radio-checked': this.checked
};
return [
<div class={radioClasses}>
<div class='radio-inner'></div>
</div>,
<button
class='radio-cover'
onClick={() => this.toggle()}
id={this.id}
aria-checked={this.checked ? 'true' : false}
aria-disabled={this.disabled ? 'true' : false}
aria-labelledby={this.labelId}
role='radio'
tabIndex={0}
/>
];
}
}
// constructor() {
// if (_group) {
// // register with the radiogroup
// this.id = 'rb-' + _group.add(this);
// }
// if (_item) {
// // register the input inside of the item
// // reset to the item's id instead of the radiogroup id
// this.id = 'rb-' + _item.registerInput('radio');
// this._labelId = 'lbl-' + _item.id;
// this._item.setElementClass('item-radio', true);
// }
// }
// /**
// * @internal
// */
// ngOnInit() {
// if (this._group && isPresent(this._group.value)) {
// this.checked = isCheckedProperty(this._group.value, this.value);
// }
// if (this._group && this._group.disabled) {
// this.disabled = this._group.disabled;
// }
// }

View File

@ -0,0 +1,177 @@
@import "../../themes/ionic.globals.wp";
@import "./radio";
// Windows Radio
// --------------------------------------------------
/// @prop - Color of the checked radio
$radio-wp-color-on: color($colors-wp, primary) !default;
/// @prop - Color of the unchecked radio
$radio-wp-color-off: #333 !default;
/// @prop - Order of the radio (places to the left of the item)
$radio-wp-order: -1 !default;
/// @prop - Width of the radio icon
$radio-wp-icon-width: 16px !default;
/// @prop - Height of the radio icon
$radio-wp-icon-height: 16px !default;
/// @prop - Border width of the radio icon
$radio-wp-icon-border-width: 2px !default;
/// @prop - Border style of the radio icon
$radio-wp-icon-border-style: solid !default;
/// @prop - Border radius of the radio icon
$radio-wp-icon-border-radius: 50% !default;
/// @prop - Opacity of the disabled radio
$radio-wp-disabled-opacity: .3 !default;
// deprecated
$radio-wp-item-left-margin: null !default;
/// @prop - Margin top of the item-start in a radio
$radio-wp-item-start-margin-top: 9px !default;
/// @prop - Margin end of the item-start in a radio
$radio-wp-item-start-margin-end: 20px !default;
/// @prop - Margin bottom of the item-start in a radio
$radio-wp-item-start-margin-bottom: 9px !default;
/// @prop - Margin start of the item-start in a radio
$radio-wp-item-start-margin-start: 4px !default;
// deprecated
$radio-wp-item-right-margin: null !default;
/// @prop - Margin top of the item-end in a radio
$radio-wp-item-end-margin-top: 11px !default;
/// @prop - Margin end of the item-end in a radio
$radio-wp-item-end-margin-end: 10px !default;
/// @prop - Margin bottom of the item-end in a radio
$radio-wp-item-end-margin-bottom: 10px !default;
/// @prop - Margin start of the item-end in a radio
$radio-wp-item-end-margin-start: 0 !default;
// Windows Radio Outer Circle: Unchecked
// -----------------------------------------
.radio-wp .radio-icon {
@include position(0, null, null, 0);
@include margin(0);
@include border-radius($radio-wp-icon-border-radius);
position: relative;
display: block;
width: $radio-wp-icon-width;
height: $radio-wp-icon-height;
border-width: $radio-wp-icon-border-width;
border-style: $radio-wp-icon-border-style;
border-color: $radio-wp-color-off;
}
// Windows Radio Inner Circle: Unchecked
// -----------------------------------------
.radio-wp .radio-inner {
@include position($radio-wp-icon-border-width, null, null, $radio-wp-icon-border-width);
@include border-radius(50%);
position: absolute;
display: none;
width: $radio-wp-icon-width / 2;
height: $radio-wp-icon-height / 2;
background-color: $radio-wp-color-off;
}
// Windows Radio Outer Circle: Checked
// -----------------------------------------
.radio-wp .radio-checked {
border-color: $radio-wp-color-on;
}
// Windows Radio Inner Circle: Checked
// -----------------------------------------
.radio-wp .radio-checked .radio-inner {
// transform: scale3d(1, 1, 1);
display: block;
}
// Windows Radio: Disabled
// -----------------------------------------
.radio-wp.radio-disabled,
.item-wp.item-radio-disabled ion-label {
opacity: $radio-wp-disabled-opacity;
pointer-events: none;
}
// Windows Radio Within An Item
// -----------------------------------------
.item-wp .radio-wp {
position: static;
display: block;
order: $radio-wp-order;
@include deprecated-variable(margin, $radio-wp-item-left-margin) {
@include margin($radio-wp-item-start-margin-top, $radio-wp-item-start-margin-end, $radio-wp-item-start-margin-bottom, $radio-wp-item-start-margin-start);
}
&[item-right], // deprecated
&[item-end] {
order: 0;
@include deprecated-variable(margin, $radio-wp-item-right-margin) {
@include margin($radio-wp-item-end-margin-top, $radio-wp-item-end-margin-end, $radio-wp-item-end-margin-bottom, $radio-wp-item-end-margin-start);
}
}
}
.item-radio.item-wp ion-label {
@include margin-horizontal(0, null);
}
// Windows Radio Color Mixin
// --------------------------------------------------
@mixin radio-theme-wp($color-name, $color-base) {
.radio-wp-#{$color-name} .radio-checked {
border-color: $color-base;
}
}
// Generate Windows Radio Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
@include radio-theme-wp($color-name, $color-base);
}

View File

@ -0,0 +1,136 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Ionic Radio</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-header>
<ion-toolbar>
<ion-title>Radios</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="outer-content">
<ion-radio-group>
<ion-list>
<ion-list-header>
Fruits
</ion-list-header>
<ion-item>
<ion-label>Apple</ion-label>
<ion-radio slot="start" name="apple" checked></ion-radio>
<ion-icon slot="end" name="ionic"></ion-icon>
</ion-item>
<ion-item>
<ion-label>Banana</ion-label>
<ion-radio slot="start" name="banana" checked></ion-radio>
</ion-item>
<ion-item>
<ion-label>Cherry</ion-label>
<ion-radio slot="start" color="danger" name="cherry"></ion-radio>
</ion-item>
</ion-list>
</ion-radio-group>
<ion-list>
<ion-list-header>
Mo Fruits
</ion-list-header>
<ion-item>
<ion-label>Grape, checked, disabled</ion-label>
<ion-radio slot="start" id="grapeChecked" name="grape" checked disabled></ion-radio>
</ion-item>
<ion-item>
<ion-label>Kiwi, (ionChange) Secondary color</ion-label>
<ion-radio slot="start" color="secondary" (ionChange)="kiwiChange($event)"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Strawberry, (ionChange) checked="true"</ion-label>
<ion-radio slot="start" color="light" (ionChange)="strawberryChange($event)" checked="true"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Checkbox right, checked, really long text that should ellipsis</ion-label>
<ion-radio slot="end" color="danger" checked></ion-radio>
</ion-item>
<ion-item>
<ion-label>Checkbox right side</ion-label>
<ion-radio slot="end" checked></ion-radio>
</ion-item>
<ion-item>
<ion-label>Button w/ right side default icon, really long text that should ellipsis</ion-label>
<ion-icon name="information-circle" slot="end"></ion-icon>
</ion-item>
</ion-list>
<p aria-hidden="true" text-center>
<ion-button onClick="toggleBoolean('grapeChecked', 'checked')" outline small>Grape Checked</ion-button>
<ion-button onClick="toggleBoolean('grapeChecked', 'disabled')" outline small>Grape Disabled</ion-button>
<ion-button onClick="printForm()" outline small>Print Form</ion-button>
</p>
<p>
<ion-radio id="standAloneChecked"></ion-radio>
Stand-alone checkbox: <span id="standAloneCheckedSpan"></span>
</p>
<p aria-hidden="true" padding>
<code>appleCtrl.value: <span id="appleCtrlValue"></span></code><br>
<code>bananaCtrl.value: <span id="bananaCtrlValue"></span></code><br>
<code>cherry.value: <span id="cherryCtrlValue"></span></code><br>
<code>grape.value: <span id="grapeCtrlValue"></span></code><br>
<code>kiwiValue: <spa id="kiwiValue"></span></code><br>
<code>strawberryValue: <span id="strawberryValue">y</span></code><br>
</p>
<pre aria-hidden="true" padding id="formResults"></pre>
<ion-item>
<ion-label>Checkbox / Toggle</ion-label>
<ion-radio slot="start" id="checked"></ion-radio>
<ion-toggle id="checked"></ion-toggle>
</ion-item>
<ion-item>
<ion-label>Checked</ion-label>
<ion-radio slot="start" checked></ion-radio>
<ion-toggle checked></ion-toggle>
</ion-item>
<ion-item>
<ion-label>Disabled</ion-label>
<ion-radio slot="start" disabled></ion-radio>
<ion-toggle disabled></ion-toggle>
</ion-item>
</ion-content>
<script>
function printForm(ev) {
console.log('TODO get working with forms');
}
function toggleBoolean(id, prop) {
var ele = document.getElementById(id);
var isTrue = ele[prop] ? false : true;
ele[prop] = isTrue;
console.log('in toggleBoolean, setting', prop, 'to', isTrue);
}
</script>
</ion-app>
</body>
</html>

View File

@ -18,6 +18,25 @@ export function isFunction(v: any): v is (Function) { return typeof v === 'funct
export function isStringOrNumber(v: any): v is (string | number) { return isString(v) || isNumber(v); }
/** @hidden */
export function isCheckedProperty(a: any, b: any): boolean {
if (a === undefined || a === null || a === '') {
return (b === undefined || b === null || b === '');
} else if (a === true || a === 'true') {
return (b === true || b === 'true');
} else if (a === false || a === 'false') {
return (b === false || b === 'false');
} else if (a === 0 || a === '0') {
return (b === 0 || b === '0');
}
// not using strict comparison on purpose
return (a == b); // tslint:disable-line
};
export function assert(bool: boolean, msg: string) {
if (!bool) {
console.error(msg);