ionic-selectable
v7.0.2
Published
An Ionic component similar to Ionic Select, that allows to search items, including async search, group, add, edit, delete items, and much more.
Readme
Ionic Selectable
Features | Getting started | Virtual scroll | FAQ | Docs
An Ionic component similar to Ionic Select, that allows to search items, including async search, infinite scrolling, virtual scrolling and more.

Which package am I looking at? This is the Angular component. There is also a separate Stencil-based line that ships web components for vanilla JS and other frameworks. The instructions below are for the Angular package.
Contents
Compatibility
| ionic-selectable | Ionic | Angular | | ---------------- | ----- | ------- | | 7.x | 8 | 20 – 22 | | 6.x | 7 | 16 | | 4.x | 4 | — | | 3.x | 3 | — |
7.x is a standalone build. The component, the modal and all template
directives are standalone, and Ionic is consumed through
@ionic/angular/standalone. It works both in apps bootstrapped with
provideIonicAngular() and in apps still using IonicModule.forRoot().
The package is published in Angular's partial compilation mode, so a build made with Angular 21 links cleanly into Angular 20, 21 and 22 applications.
Features
- Single selection
- Multiple selection
- Search items
- Search items asynchronously
- Search by several item fields
- Forms
- InfiniteScroll
- Virtual scroll, with group headers
- Templates
- Grouping items
- Editing, adding and deleting items
- Disabling items
Getting started
1. Install it
npm install ionic-selectable --save@angular/cdk is a peer dependency — it powers the virtual scroll viewport —
so install it too if your app doesn't have it already:
npm install @angular/cdk --save2. Import it
Because the component is standalone, import it directly into whichever component uses it:
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonItem, IonLabel } from '@ionic/angular/standalone';
import { IonicSelectableComponent } from 'ionic-selectable';
@Component({
selector: 'app-home',
templateUrl: './home.page.html',
imports: [FormsModule, IonItem, IonLabel, IonicSelectableComponent]
})
export class HomePage { }If you use the template directives (ionicSelectableItemTemplate,
ionicSelectableValueTemplate, …), import them alongside the component, or
import IonicSelectableModule, which re-exports the component and every
directive at once:
import { IonicSelectableModule } from 'ionic-selectable';
@Component({
// ...
imports: [IonicSelectableModule]
})
export class HomePage { }IonicSelectableModule is also still a valid NgModule import, so existing
module-based apps keep working unchanged:
@NgModule({
imports: [IonicSelectableModule]
})
export class AppModule { }For Angular 16 standalone component
import { IonicSelectableComponent } from 'ionic-selectable';
@Component({
...,
standalone: true,
imports: [IonicSelectableComponent]
})
3. Add it to the template
<ion-item>
<ion-label>Port</ion-label>
<ionic-selectable
[(ngModel)]="port"
[items]="ports"
itemValueField="id"
itemTextField="name"
[canSearch]="true"
(onChange)="portChange($event)">
</ionic-selectable>
</ion-item>4. Configure it
import { Component } from '@angular/core';
import { IonicSelectableComponent } from 'ionic-selectable';
interface Port {
id: number;
name: string;
}
@Component({ /* ... */ })
export class HomePage {
ports: Port[] = [
{ id: 1, name: 'Tokai' },
{ id: 2, name: 'Vladivostok' },
{ id: 3, name: 'Navlakhi' }
];
port: Port | undefined;
portChange(event: { component: IonicSelectableComponent; value: any }) {
console.log('port:', event.value);
}
}5. Enjoy it 😉
Explore the docs and FAQ to learn more about its features, and run the demo app in this repo to see every option in action.
Virtual scroll
Set hasVirtualScroll when the list is long enough that rendering every item
hurts. The modal then renders the list through an Angular CDK
virtual scroll viewport,
keeping only the visible rows in the DOM.
<ionic-selectable
[(ngModel)]="port"
[items]="ports"
itemValueField="id"
itemTextField="name"
[hasVirtualScroll]="true"
[canSearch]="true">
</ionic-selectable>Grouping
Groups and virtual scroll can be used together. Groups are flattened into a
single stream of header and item rows, so groupValueField / groupTextField
work exactly as they do in a regular list:
<ionic-selectable
[(ngModel)]="port"
[items]="ports"
itemValueField="id"
itemTextField="name"
groupValueField="country.id"
groupTextField="country.name"
[hasVirtualScroll]="true">
</ionic-selectable>When the items aren't grouped with groupValueField, headers can still be
inserted with virtualScrollHeaderFn. It receives each item and returns the
header text to render before it, or undefined for no header:
<ionic-selectable
[hasVirtualScroll]="true"
[virtualScrollHeaderFn]="getGroupText">
</ionic-selectable>getGroupText(port: Port, index: number, ports: Port[]) {
if (index === 0 || port.country.id !== ports[index - 1].country.id) {
return port.country.name;
}
return undefined;
}Row height
Rows are rendered at a fixed height, which defaults to 40px. Both items and
group headers are pinned to it. Change it with virtualScrollApproxItemHeight,
which accepts a number of pixels or a px string:
<ionic-selectable [hasVirtualScroll]="true" [virtualScrollApproxItemHeight]="56">
</ionic-selectable>The value is also exposed to CSS as --ionic-selectable-virtual-item-height on
the viewport, so custom item templates can lay themselves out against it.
Notes
- Virtual scroll and
hasInfiniteScrollare mutually exclusive. With virtual scroll enabled, infinite scroll is not rendered andenableInfiniteScroll()/disableInfiniteScroll()/endInfiniteScroll()are no-ops. scrollToTop()andscrollToBottom()operate on the viewport.- The viewport is the scrolling element, so
ion-contentscrolling is turned off while virtual scroll is on. - Searching resets the viewport back to the first row.
Development
The repo contains both the library (src/app/components/ionic-selectable) and
a demo app covering every feature (src/app/pages).
npm install # install dependencies
npm start # serve the demo app
npm run build # build the demo app
npm test # run unit tests
npm run lint # lint
npm run build.ng # build the publishable library into dist/Publishing
Always publish the built package from dist/, never from the repo root
(the root only contains sources and would ship raw .ts files without a
module/exports entry; a prepublishOnly guard blocks this by mistake):
npm version <x.y.z> --no-git-tag-version # bump version in package.json
npm run build.ng # build into dist/ (copies package.json, README, LICENSE)
cd dist && npm publish # publish the built packageFor contribution guidelines please refer to Contribution.
Share it
If you find this component useful, please star the repo to let others know that it's reliable. Also, share it with friends and colleagues who might find it useful as well. Thank you 😄
