mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
refactor(checkbox): use native input type=checkbox
This commit is contained in:
1
packages/core/src/components.d.ts
vendored
1
packages/core/src/components.d.ts
vendored
@ -594,6 +594,7 @@ declare global {
|
||||
|
||||
color?: string,
|
||||
mode?: 'ios' | 'md',
|
||||
name?: string,
|
||||
checked?: boolean,
|
||||
disabled?: boolean,
|
||||
value?: string
|
||||
|
@ -123,6 +123,27 @@ $checkbox-ios-item-end-margin-start: 0 !default;
|
||||
}
|
||||
|
||||
|
||||
// iOS Checkbox Keyboard Focus
|
||||
// -----------------------------------------
|
||||
|
||||
.checkbox-key .checkbox-icon::after {
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
left: -9px;
|
||||
|
||||
display: block;
|
||||
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
|
||||
background: #86A8DF;
|
||||
opacity: .3;
|
||||
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
}
|
||||
|
||||
|
||||
// iOS Checkbox Within An Item
|
||||
// -----------------------------------------
|
||||
|
||||
|
@ -142,6 +142,27 @@ $checkbox-md-item-end-margin-start: 0 !default;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Checkbox Keyboard Focus
|
||||
// -----------------------------------------
|
||||
|
||||
.checkbox-key .checkbox-icon::after {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
left: -12px;
|
||||
|
||||
display: block;
|
||||
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
|
||||
background: #86A8DF;
|
||||
opacity: .3;
|
||||
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
}
|
||||
|
||||
|
||||
// Material Design Checkbox Within An Item
|
||||
// -----------------------------------------
|
||||
|
||||
|
@ -9,7 +9,7 @@ ion-checkbox {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.checkbox-cover {
|
||||
ion-checkbox input {
|
||||
@include position(0, null, null, 0);
|
||||
|
||||
position: absolute;
|
||||
@ -19,4 +19,8 @@ ion-checkbox {
|
||||
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BlurEvent, CheckboxInput, CheckedInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { Component, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChange } from '@stencil/core';
|
||||
import { Component, CssClassMap, Event, EventEmitter, Prop, PropDidChange, State } from '@stencil/core';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -13,10 +13,46 @@ import { Component, CssClassMap, Event, EventEmitter, Listen, Prop, PropDidChang
|
||||
}
|
||||
})
|
||||
export class Checkbox implements CheckboxInput {
|
||||
private checkboxId: string;
|
||||
private labelId: string;
|
||||
private didLoad: boolean;
|
||||
private inputId: string;
|
||||
private nativeInput: HTMLInputElement;
|
||||
private styleTmr: any;
|
||||
|
||||
@State() keyFocus: boolean;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Prop() color: string;
|
||||
|
||||
/**
|
||||
* @input {string} The mode determines which platform styles to use.
|
||||
* Possible values are: `"ios"` or `"md"`.
|
||||
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
*/
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Prop() name: string;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, the checkbox is selected. Defaults to `false`.
|
||||
*/
|
||||
@Prop({ mutable: true }) checked = false;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the checkbox. Default false.
|
||||
*/
|
||||
@Prop() disabled = false;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the checkbox.
|
||||
*/
|
||||
@Prop({ mutable: true }) value: string;
|
||||
|
||||
/**
|
||||
* @output {Event} Emitted when the checked property has changed.
|
||||
*/
|
||||
@ -37,55 +73,51 @@ export class Checkbox implements CheckboxInput {
|
||||
*/
|
||||
@Event() ionStyle: EventEmitter<StyleEvent>;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Prop() color: string;
|
||||
|
||||
/**
|
||||
* @input {string} The mode determines which platform styles to use.
|
||||
* Possible values are: `"ios"` or `"md"`.
|
||||
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
*/
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, the checkbox is selected. Defaults to `false`.
|
||||
*/
|
||||
@Prop({ mutable: true }) checked: boolean = false;
|
||||
|
||||
/*
|
||||
* @input {boolean} If true, the user cannot interact with the checkbox. Default false.
|
||||
*/
|
||||
@Prop() disabled: boolean = false;
|
||||
|
||||
/**
|
||||
* @input {string} the value of the checkbox.
|
||||
*/
|
||||
@Prop({ mutable: true }) value: string;
|
||||
|
||||
|
||||
componentWillLoad() {
|
||||
this.inputId = 'ion-cb-' + (checkboxIds++);
|
||||
if (this.value === undefined) {
|
||||
this.value = this.inputId;
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PropDidChange('checked')
|
||||
checkedChanged(isChecked: boolean) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
if (this.nativeInput.checked !== isChecked) {
|
||||
// keep the checked value and native input `nync
|
||||
this.nativeInput.checked = isChecked;
|
||||
}
|
||||
if (this.didLoad) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@PropDidChange('disabled')
|
||||
disabledChanged() {
|
||||
disabledChanged(isDisabled: boolean) {
|
||||
this.nativeInput.disabled = isDisabled;
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
private emitStyle() {
|
||||
emitStyle() {
|
||||
clearTimeout(this.styleTmr);
|
||||
|
||||
this.styleTmr = setTimeout(() => {
|
||||
@ -96,22 +128,29 @@ export class Checkbox implements CheckboxInput {
|
||||
});
|
||||
}
|
||||
|
||||
@Listen('keydown.space')
|
||||
onSpace(ev: KeyboardEvent) {
|
||||
this.toggle();
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
onChange() {
|
||||
this.checked = !this.checked;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.checked = !this.checked;
|
||||
onKeyUp() {
|
||||
this.keyFocus = true;
|
||||
}
|
||||
|
||||
onFocus() {
|
||||
this.ionFocus.emit();
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
this.keyFocus = false;
|
||||
this.ionBlur.emit();
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
'checkbox-checked': this.checked,
|
||||
'checkbox-disabled': this.disabled
|
||||
'checkbox-disabled': this.disabled,
|
||||
'checkbox-key': this.keyFocus
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -126,16 +165,19 @@ export class Checkbox implements CheckboxInput {
|
||||
<div class={checkboxClasses}>
|
||||
<div class='checkbox-inner'></div>
|
||||
</div>,
|
||||
<button
|
||||
class='checkbox-cover'
|
||||
onClick={() => this.toggle()}
|
||||
id={this.checkboxId}
|
||||
aria-checked={this.checked ? 'true' : false}
|
||||
aria-disabled={this.disabled ? 'true' : false}
|
||||
aria-labelledby={this.labelId}
|
||||
role='checkbox'
|
||||
tabIndex={0}
|
||||
/>
|
||||
<input
|
||||
type='checkbox'
|
||||
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)}/>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
let checkboxIds = 0;
|
||||
|
@ -10,50 +10,22 @@ Placed in an `ion-item` or used as a stand-alone checkbox.
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Pepperoni</ion-label>
|
||||
<ion-checkbox [(ngModel)]="pepperoni"></ion-checkbox>
|
||||
<ion-checkbox value="pepperoni" checked></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Sausage</ion-label>
|
||||
<ion-checkbox [(ngModel)]="sausage" disabled="true"></ion-checkbox>
|
||||
<ion-checkbox value="sausage" disabled></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Mushrooms</ion-label>
|
||||
<ion-checkbox [(ngModel)]="mushrooms"></ion-checkbox>
|
||||
<ion-checkbox value="mushrooms"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
```
|
||||
|
||||
@advanced
|
||||
|
||||
```html
|
||||
|
||||
<!-- Call function when state changes -->
|
||||
<ion-list>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Cucumber</ion-label>
|
||||
<ion-checkbox [(ngModel)]="cucumber" (ionChange)="updateCucumber()"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
```
|
||||
|
||||
```ts
|
||||
@Component({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class SaladPage {
|
||||
cucumber: boolean;
|
||||
|
||||
updateCucumber() {
|
||||
console.log('Cucumbers new state:' + this.cucumber);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
@ -40,6 +40,10 @@
|
||||
<ion-label>Dark</ion-label>
|
||||
<ion-checkbox color="dark" checked></ion-checkbox>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Unchecked by Default</ion-label>
|
||||
<ion-checkbox></ion-checkbox>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Disabled</ion-label>
|
||||
<ion-checkbox disabled></ion-checkbox>
|
||||
|
Reference in New Issue
Block a user