mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
fix(select): set the proper values for select for all interfaces
This commit is contained in:
@ -20,7 +20,7 @@ export class SelectOption {
|
|||||||
/**
|
/**
|
||||||
* @input {boolean} If true, the element is selected.
|
* @input {boolean} If true, the element is selected.
|
||||||
*/
|
*/
|
||||||
@Prop() selected: boolean = false;
|
@Prop({state: true}) selected: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {string} The text value of the option.
|
* @input {string} The text value of the option.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
import { Component, Prop, PropDidChange } from '@stencil/core';
|
import { Component, Event, EventEmitter, Listen, Prop, PropDidChange } from '@stencil/core';
|
||||||
|
|
||||||
|
import { createThemedClasses } from '../../utils/theme';
|
||||||
|
|
||||||
export interface SelectPopoverOption {
|
export interface SelectPopoverOption {
|
||||||
text: string;
|
text: string;
|
||||||
@ -10,16 +12,24 @@ export interface SelectPopoverOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
tag: 'ion-select-popover'
|
tag: 'ion-select-popover',
|
||||||
})
|
host: {
|
||||||
|
theme: 'select-popover'
|
||||||
|
}}
|
||||||
|
)
|
||||||
export class SelectPopover {
|
export class SelectPopover {
|
||||||
|
mode: string;
|
||||||
|
color: string;
|
||||||
|
|
||||||
|
@Event() ionDismiss: EventEmitter;
|
||||||
|
|
||||||
@Prop() options: SelectPopoverOption[];
|
@Prop() options: SelectPopoverOption[];
|
||||||
|
|
||||||
@Prop({ mutable: true }) value: string;
|
@Prop({ mutable: true }) value: string;
|
||||||
|
|
||||||
@PropDidChange('value')
|
@Listen('ionChange')
|
||||||
valueChanged(val: string) {
|
onChange(ev: CustomEvent) {
|
||||||
console.log('Select popover value', val);
|
this.value = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public get value() {
|
// public get value() {
|
||||||
@ -28,25 +38,36 @@ export class SelectPopover {
|
|||||||
// return checkedOption ? checkedOption.value : undefined;
|
// return checkedOption ? checkedOption.value : undefined;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// public set value(value: any) {
|
dismiss(value: any) {
|
||||||
// let checkedOption = this.options.find(option => option.value === value);
|
this.ionDismiss.emit(value);
|
||||||
// if (checkedOption && checkedOption.handler) {
|
}
|
||||||
// checkedOption.handler();
|
|
||||||
// }
|
@PropDidChange('value')
|
||||||
// this.viewController.dismiss(value);
|
valueChanged(value: string) {
|
||||||
// }
|
let checkedOption = this.options.find(option => option.value === value);
|
||||||
|
if (checkedOption && checkedOption.handler) {
|
||||||
|
checkedOption.handler();
|
||||||
|
}
|
||||||
|
this.dismiss(value);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log(this.options);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ion-list radio-group value="{this.value}">
|
<ion-list>
|
||||||
{this.options.map(option =>
|
<ion-radio-group value={this.value}>
|
||||||
<ion-item>
|
{this.options.map(option =>
|
||||||
<ion-label>{option.text}</ion-label>
|
<ion-item>
|
||||||
<ion-radio checked={option.checked} value={option.value} disabled={option.disabled}></ion-radio>
|
<ion-label>
|
||||||
</ion-item>
|
{option.text}
|
||||||
)}
|
</ion-label>
|
||||||
|
<ion-radio
|
||||||
|
checked={option.checked}
|
||||||
|
value={option.value}
|
||||||
|
disabled={option.disabled}>
|
||||||
|
</ion-radio>
|
||||||
|
</ion-item>
|
||||||
|
)}
|
||||||
|
</ion-radio-group>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Component, CssClassMap, Element, Event, EventEmitter, HostElement, Prop } from '@stencil/core';
|
import { Component, CssClassMap, Element, Event, EventEmitter, HostElement, Prop, PropDidChange, State } from '@stencil/core';
|
||||||
|
|
||||||
import { deepCopy } from '../../utils/helpers';
|
import { deepCopy, isCheckedProperty } from '../../utils/helpers';
|
||||||
|
|
||||||
import { ActionSheet } from '../action-sheet/action-sheet';
|
import { ActionSheet } from '../action-sheet/action-sheet';
|
||||||
import { Alert } from '../alert/alert';
|
import { Alert } from '../alert/alert';
|
||||||
import { Popover } from '../popover/popover';
|
import { Popover } from '../popover/popover';
|
||||||
|
|
||||||
|
import { SelectOption } from '../select-option/select-option';
|
||||||
|
|
||||||
import { ActionSheetController } from '../action-sheet-controller/action-sheet-controller';
|
import { ActionSheetController } from '../action-sheet-controller/action-sheet-controller';
|
||||||
import { AlertController } from '../alert-controller/alert-controller';
|
import { AlertController } from '../alert-controller/alert-controller';
|
||||||
import { PopoverController } from '../popover-controller/popover-controller';
|
import { PopoverController } from '../popover-controller/popover-controller';
|
||||||
@ -23,12 +25,11 @@ import { PopoverController } from '../popover-controller/popover-controller';
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class Select {
|
export class Select {
|
||||||
text: any;
|
texts: any = [];
|
||||||
texts: any;
|
|
||||||
id: string;
|
id: string;
|
||||||
labelId: string;
|
labelId: string;
|
||||||
item: any;
|
item: any;
|
||||||
options: any;
|
options: SelectOption[] = [];
|
||||||
overlay: ActionSheet | Alert | Popover;
|
overlay: ActionSheet | Alert | Popover;
|
||||||
|
|
||||||
@Prop({ connect: 'ion-action-sheet-controller' }) actionSheetCtrl: ActionSheetController;
|
@Prop({ connect: 'ion-action-sheet-controller' }) actionSheetCtrl: ActionSheetController;
|
||||||
@ -37,6 +38,8 @@ export class Select {
|
|||||||
|
|
||||||
@Element() el: HTMLElement;
|
@Element() el: HTMLElement;
|
||||||
|
|
||||||
|
@State() text: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {boolean} If true, the user cannot interact with this element. Defaults to `false`.
|
* @input {boolean} If true, the user cannot interact with this element. Defaults to `false`.
|
||||||
*/
|
*/
|
||||||
@ -83,29 +86,12 @@ export class Select {
|
|||||||
/**
|
/**
|
||||||
* @input {string} the value of the select.
|
* @input {string} the value of the select.
|
||||||
*/
|
*/
|
||||||
@Prop({ mutable: true }) value: string;
|
@Prop({ mutable: true }) value: string | string[];
|
||||||
|
|
||||||
// /**
|
@PropDidChange('value')
|
||||||
// * @hidden
|
valueChanged() {
|
||||||
// */
|
this.optionUpdated();
|
||||||
// _inputUpdated() {
|
}
|
||||||
// this._texts.length = 0;
|
|
||||||
|
|
||||||
// if (this._options) {
|
|
||||||
// this._options.forEach(option => {
|
|
||||||
// // check this option if the option's value is in the values array
|
|
||||||
// option.selected = this.getValues().some(selectValue => {
|
|
||||||
// return isCheckedProperty(selectValue, option.value);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (option.selected) {
|
|
||||||
// this._texts.push(option.text);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this._text = this._texts.join(', ');
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @output {EventEmitter} Emitted when the selection is cancelled.
|
* @output {EventEmitter} Emitted when the selection is cancelled.
|
||||||
@ -113,7 +99,7 @@ export class Select {
|
|||||||
@Event() ionCancel: EventEmitter;
|
@Event() ionCancel: EventEmitter;
|
||||||
|
|
||||||
|
|
||||||
ionViewWillLoad() {
|
ionViewDidLoad() {
|
||||||
// Get the parent item
|
// Get the parent item
|
||||||
this.item = this.el.closest('ion-item') as HostElement;
|
this.item = this.el.closest('ion-item') as HostElement;
|
||||||
|
|
||||||
@ -123,22 +109,59 @@ export class Select {
|
|||||||
|
|
||||||
setOptions() {
|
setOptions() {
|
||||||
// Get the options
|
// Get the options
|
||||||
this.options = this.el.querySelectorAll('ion-select-option') as NodeListOf<HostElement>;
|
const options = this.el.querySelectorAll('ion-select-option') as NodeListOf<any>;
|
||||||
|
|
||||||
|
Array.from(options).forEach(option => {
|
||||||
|
if (!option.value) {
|
||||||
|
option.value = option.getText();
|
||||||
|
}
|
||||||
|
this.options.push(option.$instance);
|
||||||
|
})
|
||||||
|
|
||||||
const values = this.getValues();
|
const values = this.getValues();
|
||||||
|
|
||||||
if (values.length === 0) {
|
if (values.length === 0) {
|
||||||
// there are no values set at this point
|
// there are no values set at this point
|
||||||
// so check to see who should be selected
|
// so check to see who should be selected
|
||||||
// we use writeValue() because we don't want to update ngModel
|
let filtered = this.options.filter(o => o.selected).map(o => o.value);
|
||||||
// this.writeValue(val.filter(o => o.selected).map(o => o.value));
|
this.value = filtered;
|
||||||
|
} else {
|
||||||
|
this.optionUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
* Update the select options when the value changes
|
||||||
|
*/
|
||||||
|
optionUpdated() {
|
||||||
|
this.texts = [];
|
||||||
|
|
||||||
|
if (this.options) {
|
||||||
|
this.options.forEach(option => {
|
||||||
|
// check this option if the option's value is in the values array
|
||||||
|
option.selected = this.getValues().some(selectValue => {
|
||||||
|
return isCheckedProperty(selectValue, option.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (option.selected) {
|
||||||
|
this.texts.push(option.getText());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.text = this.texts.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
getValues(): any[] {
|
getValues(): any[] {
|
||||||
|
if (!this.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const values = Array.isArray(this.value) ? this.value : [this.value];
|
const values = Array.isArray(this.value) ? this.value : [this.value];
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@ -188,13 +211,12 @@ export class Select {
|
|||||||
return selectInterface;
|
return selectInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add Alert to finish this
|
|
||||||
buildAlert(selectOptions: any) {
|
buildAlert(selectOptions: any) {
|
||||||
console.debug('Build Select: Alert with', selectOptions, this.options);
|
console.debug('Build Select: Alert with', selectOptions, this.options);
|
||||||
|
|
||||||
// user cannot provide inputs from selectOptions
|
// user cannot provide inputs from selectOptions
|
||||||
// alert inputs must be created by ionic from ion-select-options
|
// alert inputs must be created by ionic from ion-select-options
|
||||||
selectOptions.inputs = Array.from(this.options).map((option: any) => {
|
selectOptions.inputs = this.options.map((option: any) => {
|
||||||
return {
|
return {
|
||||||
type: (this.multiple ? 'checkbox' : 'radio'),
|
type: (this.multiple ? 'checkbox' : 'radio'),
|
||||||
label: option.getText(),
|
label: option.getText(),
|
||||||
@ -217,13 +239,15 @@ export class Select {
|
|||||||
// If the user passed a cssClass for the select, add it
|
// If the user passed a cssClass for the select, add it
|
||||||
selectCssClass += selectOptions.cssClass ? ' ' + selectOptions.cssClass : '';
|
selectCssClass += selectOptions.cssClass ? ' ' + selectOptions.cssClass : '';
|
||||||
|
|
||||||
|
// Add an ok button to the alert
|
||||||
|
selectOptions.buttons = selectOptions.buttons.concat({
|
||||||
|
text: this.okText,
|
||||||
|
handler: (selectedValues: any) => this.value = selectedValues
|
||||||
|
})
|
||||||
|
|
||||||
// create the alert instance from our built up selectOptions
|
// create the alert instance from our built up selectOptions
|
||||||
const alertOptions = {
|
const alertOptions = {
|
||||||
cssClass: selectCssClass,
|
cssClass: selectCssClass,
|
||||||
buttons: [{
|
|
||||||
text: this.okText,
|
|
||||||
handler: (selectedValues: any) => this.value = selectedValues
|
|
||||||
}],
|
|
||||||
...selectOptions
|
...selectOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,14 +258,13 @@ export class Select {
|
|||||||
buildActionSheet(selectOptions: any) {
|
buildActionSheet(selectOptions: any) {
|
||||||
console.debug('Building Select: Action Sheet with', selectOptions, this.options);
|
console.debug('Building Select: Action Sheet with', selectOptions, this.options);
|
||||||
|
|
||||||
selectOptions.buttons = selectOptions.buttons.concat(Array.from(this.options).map((option: any) => {
|
selectOptions.buttons = selectOptions.buttons.concat(this.options.map((option: any) => {
|
||||||
return {
|
return {
|
||||||
role: (option.selected ? 'selected' : ''),
|
role: (option.selected ? 'selected' : ''),
|
||||||
text: option.getText(),
|
text: option.getText(),
|
||||||
handler: () => {
|
handler: () => {
|
||||||
this.value = option.value;
|
this.value = option.value;
|
||||||
// TODO remove $instance
|
option.ionSelect.emit(option.value);
|
||||||
option.$instance.ionSelect.emit(option.value);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
@ -263,7 +286,7 @@ export class Select {
|
|||||||
buildPopover(selectOptions: any) {
|
buildPopover(selectOptions: any) {
|
||||||
console.debug('Building Select: Popover with', selectOptions, this.options);
|
console.debug('Building Select: Popover with', selectOptions, this.options);
|
||||||
|
|
||||||
selectOptions = Array.from(this.options).map((option: any) => {
|
selectOptions = this.options.map((option: any) => {
|
||||||
return {
|
return {
|
||||||
text: option.getText(),
|
text: option.getText(),
|
||||||
checked: option.selected,
|
checked: option.selected,
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Hair Color</ion-label>
|
<ion-label>Hair Color</ion-label>
|
||||||
<ion-select name="hairColor" ok-text="Okay" cancel-text="Dismiss">
|
<ion-select name="hairColor" ok-text="Okay" cancel-text="Dismiss">
|
||||||
<ion-select-option value="brown">Brown</ion-select-option>
|
<ion-select-option value="brown" selected>Brown</ion-select-option>
|
||||||
<ion-select-option value="blonde">Blonde</ion-select-option>
|
<ion-select-option value="blonde">Blonde</ion-select-option>
|
||||||
<ion-select-option value="black">Black</ion-select-option>
|
<ion-select-option value="black">Black</ion-select-option>
|
||||||
<ion-select-option value="red">Red</ion-select-option>
|
<ion-select-option value="red">Red</ion-select-option>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Date</ion-label>
|
<ion-label>Date</ion-label>
|
||||||
<ion-select (ionChange)="monthChange($event)" placeholder="Month">
|
<ion-select placeholder="Month">
|
||||||
<ion-select-option value="01">January</ion-select-option>
|
<ion-select-option value="01">January</ion-select-option>
|
||||||
<ion-select-option value="02">February</ion-select-option>
|
<ion-select-option value="02">February</ion-select-option>
|
||||||
<ion-select-option value="03" selected="true">March</ion-select-option>
|
<ion-select-option value="03" selected="true">March</ion-select-option>
|
||||||
@ -64,7 +64,7 @@
|
|||||||
<ion-select-option value="11">November</ion-select-option>
|
<ion-select-option value="11">November</ion-select-option>
|
||||||
<ion-select-option value="12">December</ion-select-option>
|
<ion-select-option value="12">December</ion-select-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
<ion-select (ionChange)="yearChange($event)" placeholder="Year">
|
<ion-select placeholder="Year">
|
||||||
<ion-select-option>1989</ion-select-option>
|
<ion-select-option>1989</ion-select-option>
|
||||||
<ion-select-option>1990</ion-select-option>
|
<ion-select-option>1990</ion-select-option>
|
||||||
<ion-select-option>1991</ion-select-option>
|
<ion-select-option>1991</ion-select-option>
|
||||||
@ -94,7 +94,7 @@
|
|||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Gaming</ion-label>
|
<ion-label>Gaming</ion-label>
|
||||||
<ion-select name="gaming" ok-text="Okay" cancel-text="Dismiss" selected-text="Nintendo 64" interface="popover">
|
<ion-select name="gaming" ok-text="Okay" cancel-text="Dismiss" value="n64" interface="popover">
|
||||||
<ion-select-option value="nes">NES</ion-select-option>
|
<ion-select-option value="nes">NES</ion-select-option>
|
||||||
<ion-select-option value="n64">Nintendo64</ion-select-option>
|
<ion-select-option value="n64">Nintendo64</ion-select-option>
|
||||||
<ion-select-option value="ps">PlayStation</ion-select-option>
|
<ion-select-option value="ps">PlayStation</ion-select-option>
|
||||||
@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Date</ion-label>
|
<ion-label>Date</ion-label>
|
||||||
<ion-select (ionChange)="monthChange($event)" placeholder="Month" interface="popover">
|
<ion-select placeholder="Month" interface="popover">
|
||||||
<ion-select-option value="01">January</ion-select-option>
|
<ion-select-option value="01">January</ion-select-option>
|
||||||
<ion-select-option value="02">February</ion-select-option>
|
<ion-select-option value="02">February</ion-select-option>
|
||||||
<ion-select-option value="03" selected="true">March</ion-select-option>
|
<ion-select-option value="03" selected="true">March</ion-select-option>
|
||||||
@ -120,7 +120,7 @@
|
|||||||
<ion-select-option value="11">November</ion-select-option>
|
<ion-select-option value="11">November</ion-select-option>
|
||||||
<ion-select-option value="12">December</ion-select-option>
|
<ion-select-option value="12">December</ion-select-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
<ion-select (ionChange)="yearChange($event)" placeholder="Year" interface="popover">
|
<ion-select placeholder="Year" interface="popover">
|
||||||
<ion-select-option>1989</ion-select-option>
|
<ion-select-option>1989</ion-select-option>
|
||||||
<ion-select-option>1990</ion-select-option>
|
<ion-select-option>1990</ion-select-option>
|
||||||
<ion-select-option>1991</ion-select-option>
|
<ion-select-option>1991</ion-select-option>
|
||||||
|
Reference in New Issue
Block a user