Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@davidgeary
Last active January 29, 2021 08:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidgeary/630ad1234ee5eedae2e1f9e6cdf82c62 to your computer and use it in GitHub Desktop.
Save davidgeary/630ad1234ee5eedae2e1f9e6cdf82c62 to your computer and use it in GitHub Desktop.
Angular directive to force selected item in Ionic 5 ionSelect component to be scrolled into view
import { Directive, HostListener } from '@angular/core';
const IONSELECT_DISPLAY_DELAY_MS: number = 250; /* In milliseconds */
/** Directive to force selected item in ionSelect component to be scrolled into view
* Provides a workaround for issue #19296 (https://github.com/ionic-team/ionic-framework/issues/19296)
*/
@Directive({
// tslint:disable-next-line: directive-selector
selector: 'ion-select'
})
export class IonselectAutoscrollDirective {
@HostListener('click') public onClick(): void {
/* HACK ALERT! Previous versions of Ionic allowed you to subscribe to events on the popover overlay via:
selectControl._overlay.didEnter.subscribe(() => {...}
You could then use setTimeout() without a delay to allow just one cycle before scrolling the list. This
is no longer available, so we're going to have to use a short delay and hope that that's enough time
for the list to be instantiated.
This is also working on the assumption that only one set of options can be displayed at a time since we
have to search for elements on the document because they're not children of (or linked by id/attribute to)
the ion-select element.
*/
setTimeout(() => {
/* Unfortunately, the different ionSelect interfaces decorate their items with different classes and use
different ways to identify the selected item:
* alert - uses the `select-interface-option` class on the button and the `aria-checked` attribute to
mark the selected item
* action-sheet - also uses the `select-interface-option` class on the button but uses the
`action-sheet-selected` class to mark the selected item
* popover - uses the `sc-ion-select-popover` class on the `ion-radio` element and the `aria-checked`
attribute to mark the selected item
So it's simpler to look for the different classes to identify each interface instead.
*/
let selectedOption: Element | null = null;
let options: HTMLCollectionOf<Element> = document.getElementsByClassName('action-sheet-button');
if (options.length > 0) {
for (const option of options as any) {
if (option.classList.contains('action-sheet-selected')) {
selectedOption = option;
break;
}
}
} else {
options = document.getElementsByClassName('alert-radio-button');
if (options.length === 0) {
options = document.getElementsByClassName('sc-ion-select-popover');
}
for (const option of options as any) {
const attribute: Attr | null = option.attributes.getNamedItem('aria-checked');
if (attribute && attribute.value === 'true') {
selectedOption = option;
break;
}
}
}
if (selectedOption) {
selectedOption.scrollIntoView({ block: 'center' });
}
}, IONSELECT_DISPLAY_DELAY_MS);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment