fix(select): fix options being added async while overlay is open (#17860)

fixes #15716
fixes #17851
This commit is contained in:
Liam DeBeasi
2019-03-26 11:29:24 -04:00
committed by GitHub
parent dceec07390
commit 1ecfcd1902
2 changed files with 104 additions and 57 deletions

View File

@ -1,6 +1,6 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Method, Prop, State, Watch } from '@stencil/core';
import { ActionSheetButton, ActionSheetOptions, AlertOptions, CssClassMap, Mode, OverlaySelect, PopoverOptions, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, StyleEventDetail } from '../../interface';
import { ActionSheetButton, ActionSheetOptions, AlertInput, AlertOptions, CssClassMap, Mode, OverlaySelect, PopoverOptions, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, StyleEventDetail } from '../../interface';
import { findItemLabel, renderHiddenInput } from '../../utils/helpers';
import { hostContext } from '../../utils/theme';
@ -143,6 +143,8 @@ export class Select implements ComponentInterface {
if (this.didInit) {
this.updateOptions();
this.updateOverlayOptions();
this.emitStyle();
/**
* In the event that options
@ -227,40 +229,29 @@ export class Select implements ComponentInterface {
return this.openAlert();
}
private async openPopover(ev: UIEvent) {
const interfaceOptions = this.interfaceOptions;
private updateOverlayOptions(): void {
if (!this.overlay) { return; }
const overlay = (this.overlay as any);
const popoverOpts: PopoverOptions = {
mode: this.mode,
...interfaceOptions,
component: 'ion-select-popover',
cssClass: ['select-popover', interfaceOptions.cssClass],
event: ev,
componentProps: {
header: interfaceOptions.header,
subHeader: interfaceOptions.subHeader,
message: interfaceOptions.message,
value: this.value,
options: this.childOpts.map(o => {
return {
text: o.textContent,
value: o.value,
checked: o.selected,
disabled: o.disabled,
handler: () => {
this.value = o.value;
this.close();
switch (this.interface) {
case 'action-sheet':
overlay.buttons = this.createActionSheetButtons(this.childOpts);
break;
case 'popover':
const popover = overlay.querySelector('ion-select-popover');
if (popover) {
popover.options = this.createPopoverOptions(this.childOpts);
}
} as SelectPopoverOption;
})
break;
default:
const inputType = (this.multiple ? 'checkbox' : 'radio');
overlay.inputs = this.createAlertInputs(this.childOpts, inputType);
break;
}
};
return this.popoverCtrl.create(popoverOpts);
}
private async openActionSheet() {
const actionSheetButtons = this.childOpts.map(option => {
private createActionSheetButtons(data: any[]): ActionSheetButton[] {
const actionSheetButtons = data.map(option => {
return {
role: (option.selected ? 'selected' : ''),
text: option.textContent,
@ -279,12 +270,65 @@ export class Select implements ComponentInterface {
}
});
return actionSheetButtons;
}
private createAlertInputs(data: any[], inputType: string): AlertInput[] {
return data.map(o => {
return {
type: inputType,
label: o.textContent,
value: o.value,
checked: o.selected,
disabled: o.disabled
} as AlertInput;
});
}
private createPopoverOptions(data: any[]): SelectPopoverOption[] {
return data.map(o => {
return {
text: o.textContent,
value: o.value,
checked: o.selected,
disabled: o.disabled,
handler: () => {
this.value = o.value;
this.close();
}
} as SelectPopoverOption;
});
}
private async openPopover(ev: UIEvent) {
const interfaceOptions = this.interfaceOptions;
const popoverOpts: PopoverOptions = {
mode: this.mode,
...interfaceOptions,
component: 'ion-select-popover',
cssClass: ['select-popover', interfaceOptions.cssClass],
event: ev,
componentProps: {
header: interfaceOptions.header,
subHeader: interfaceOptions.subHeader,
message: interfaceOptions.message,
value: this.value,
options: this.createPopoverOptions(this.childOpts)
}
};
return this.popoverCtrl.create(popoverOpts);
}
private async openActionSheet() {
const interfaceOptions = this.interfaceOptions;
const actionSheetOpts: ActionSheetOptions = {
mode: this.mode,
...interfaceOptions,
buttons: actionSheetButtons,
buttons: this.createActionSheetButtons(this.childOpts),
cssClass: ['select-action-sheet', interfaceOptions.cssClass]
};
return this.actionSheetCtrl.create(actionSheetOpts);
@ -302,15 +346,7 @@ export class Select implements ComponentInterface {
...interfaceOptions,
header: interfaceOptions.header ? interfaceOptions.header : labelText,
inputs: this.childOpts.map(o => {
return {
type: inputType,
label: o.textContent,
value: o.value,
checked: o.selected,
disabled: o.disabled
};
}),
inputs: this.createAlertInputs(this.childOpts, inputType),
buttons: [
{
text: this.cancelText,

View File

@ -12,14 +12,25 @@
</head>
<body>
<ion-select id="animals" placeholder="Select One"></ion-select>
<ion-select id="default" placeholder="Default"></ion-select>
<ion-select id="popover" interface="popover" placeholder="Popover"></ion-select>
<ion-select id="actionSheet" interface="action-sheet" placeholder="Action Sheet"></ion-select>
<ion-item>
<ion-label position="floating">Label w/o Placeholder</ion-label>
<ion-select id="actionSheet" interface="action-sheet"></ion-select>
</ion-item>
<ion-item>
<ion-label position="floating">Label with Placeholder</ion-label>
<ion-select id="actionSheet" interface="action-sheet" placeholder="A Placeholder"></ion-select>
</ion-item>
<script>
let select = document.getElementById('animals');
let selects = document.querySelectorAll('ion-select');
const options = ['bird', 'dog', 'shark', 'lizard'];
setTimeout(() => {
selects.forEach(select => {
options.forEach(option => {
let o = document.createElement('ion-select-option');
o.value = option;
@ -29,8 +40,8 @@
});
select.value = options[0];
}, 500);
});
}, 5000);
</script>
</body>