Skip to content
Permalink
Browse files

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

)

fixes #15716
fixes #17851
  • Loading branch information...
liamdebeasi committed Mar 26, 2019
1 parent dceec07 commit 1ecfcd190295ac523bb99e6070a6a99bd19f4827
Showing with 103 additions and 56 deletions.
  1. +77 −41 core/src/components/select/select.tsx
  2. +26 −15 core/src/components/select/test/async/index.html
@@ -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,6 +229,77 @@ export class Select implements ComponentInterface {
return this.openAlert();
}

private updateOverlayOptions(): void {
if (!this.overlay) { return; }
const overlay = (this.overlay as any);

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);
}
break;
default:
const inputType = (this.multiple ? 'checkbox' : 'radio');
overlay.inputs = this.createAlertInputs(this.childOpts, inputType);
break;
}
}

private createActionSheetButtons(data: any[]): ActionSheetButton[] {
const actionSheetButtons = data.map(option => {
return {
role: (option.selected ? 'selected' : ''),
text: option.textContent,
handler: () => {
this.value = option.value;
}
} as ActionSheetButton;
});

// Add "cancel" button
actionSheetButtons.push({
text: this.cancelText,
role: 'cancel',
handler: () => {
this.ionCancel.emit();
}
});

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;

@@ -242,49 +315,20 @@ export class Select implements ComponentInterface {
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;
})
options: this.createPopoverOptions(this.childOpts)
}
};
return this.popoverCtrl.create(popoverOpts);
}

private async openActionSheet() {
const actionSheetButtons = this.childOpts.map(option => {
return {
role: (option.selected ? 'selected' : ''),
text: option.textContent,
handler: () => {
this.value = option.value;
}
} as ActionSheetButton;
});

// Add "cancel" button
actionSheetButtons.push({
text: this.cancelText,
role: 'cancel',
handler: () => {
this.ionCancel.emit();
}
});

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,
@@ -12,26 +12,37 @@
</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(() => {
options.forEach(option => {
let o = document.createElement('ion-select-option');
o.value = option;
o.textContent = option;
select.appendChild(o);
selects.forEach(select => {
options.forEach(option => {
let o = document.createElement('ion-select-option');
o.value = option;
o.textContent = option;
select.appendChild(o);
});
select.value = options[0];
});
select.value = options[0];
}, 500);
}, 5000);
</script>
</body>
</html>

0 comments on commit 1ecfcd1

Please sign in to comment.
You can’t perform that action at this time.