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 { 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 { findItemLabel, renderHiddenInput } from '../../utils/helpers';
import { hostContext } from '../../utils/theme'; import { hostContext } from '../../utils/theme';
@ -143,6 +143,8 @@ export class Select implements ComponentInterface {
if (this.didInit) { if (this.didInit) {
this.updateOptions(); this.updateOptions();
this.updateOverlayOptions();
this.emitStyle();
/** /**
* In the event that options * In the event that options
@ -227,40 +229,29 @@ export class Select implements ComponentInterface {
return this.openAlert(); return this.openAlert();
} }
private async openPopover(ev: UIEvent) { private updateOverlayOptions(): void {
const interfaceOptions = this.interfaceOptions; if (!this.overlay) { return; }
const overlay = (this.overlay as any);
const popoverOpts: PopoverOptions = { switch (this.interface) {
mode: this.mode, case 'action-sheet':
...interfaceOptions, overlay.buttons = this.createActionSheetButtons(this.childOpts);
break;
component: 'ion-select-popover', case 'popover':
cssClass: ['select-popover', interfaceOptions.cssClass], const popover = overlay.querySelector('ion-select-popover');
event: ev, if (popover) {
componentProps: { popover.options = this.createPopoverOptions(this.childOpts);
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();
} }
} 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() { private createActionSheetButtons(data: any[]): ActionSheetButton[] {
const actionSheetButtons = this.childOpts.map(option => { const actionSheetButtons = data.map(option => {
return { return {
role: (option.selected ? 'selected' : ''), role: (option.selected ? 'selected' : ''),
text: option.textContent, 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 interfaceOptions = this.interfaceOptions;
const actionSheetOpts: ActionSheetOptions = { const actionSheetOpts: ActionSheetOptions = {
mode: this.mode, mode: this.mode,
...interfaceOptions, ...interfaceOptions,
buttons: actionSheetButtons, buttons: this.createActionSheetButtons(this.childOpts),
cssClass: ['select-action-sheet', interfaceOptions.cssClass] cssClass: ['select-action-sheet', interfaceOptions.cssClass]
}; };
return this.actionSheetCtrl.create(actionSheetOpts); return this.actionSheetCtrl.create(actionSheetOpts);
@ -302,15 +346,7 @@ export class Select implements ComponentInterface {
...interfaceOptions, ...interfaceOptions,
header: interfaceOptions.header ? interfaceOptions.header : labelText, header: interfaceOptions.header ? interfaceOptions.header : labelText,
inputs: this.childOpts.map(o => { inputs: this.createAlertInputs(this.childOpts, inputType),
return {
type: inputType,
label: o.textContent,
value: o.value,
checked: o.selected,
disabled: o.disabled
};
}),
buttons: [ buttons: [
{ {
text: this.cancelText, text: this.cancelText,

View File

@ -12,14 +12,25 @@
</head> </head>
<body> <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> <script>
let select = document.getElementById('animals'); let selects = document.querySelectorAll('ion-select');
const options = ['bird', 'dog', 'shark', 'lizard']; const options = ['bird', 'dog', 'shark', 'lizard'];
setTimeout(() => { setTimeout(() => {
selects.forEach(select => {
options.forEach(option => { options.forEach(option => {
let o = document.createElement('ion-select-option'); let o = document.createElement('ion-select-option');
o.value = option; o.value = option;
@ -29,8 +40,8 @@
}); });
select.value = options[0]; select.value = options[0];
});
}, 500); }, 5000);
</script> </script>
</body> </body>