Skip to content

iVantage/angular-ivh-multi-select

Repository files navigation

ivh.multiSelect

Build Status

An elegant and efficient multi select for AngularJS apps.

IVH Multi Select aims to provide a robust multiselect component while keeping a careful eye on performance and minizing watch counts. While collapsed IVH Multi Select will create just ~10 watchers, and only ~40 while expanded.

Note that IVH Multi Select assumes Bootstrap 3 styles.

Installation

Install with bower:

bower install --save angular-ivh-multi-select

Note: You may optionally include angular-ivh-auto-focus as well to automatically focus multi select input controls. See the auto focus section below for detail.

Usage

Add this module as a dependency to your app:

angular.module('myApp', ['ivh.multiSelect']);

At a minimum you must provide a collection of items to select from:

<div ivh-multi-select
     ivh-multi-select-items="myCollection">
  Choose some items!
</div>

IVH Multi Select will display a button that when clicked shows a menu of items to select complete with checkboxes and pagination if availabe.

We're using the selection-model component to manage selections internally. You can configure this directive's behavior by working with the selectionModelOptionsProvider. Inline selection-model-* attributes will also be forwarded to the underlying selection model:

<div ivh-multi-select
     ivh-multi-select-items="myCollection"
     selection-model-selected-attribute="'customSelectedAttr'">
  Choose some items!
</div>

This includes selection-model-on-change with the notable exception that when this expression is evaluated IVH Multi Select will provide a scope variable, item, which will be a reference to the collection item whose selected status has changed.

Labels

Labels can be pulled from collection item properties or created with a custom expression:

<div ivh-multi-select
     ivh-multi-select-items="myCollection"
     ivh-multi-select-label-attribute="'name'">
  Use "name" attribute for item labels
</div>

<!--
  Note: Use `item` to reference the current item in your label expression.
-->
<div ivh-multi-select
     ivh-multi-select-items="myCollection"
     ivh-multi-select-label-expression="'{{item.firstName}} {{item.lastName}}'">
  Use an angular expression for item labels
</div>

Pagination

In keeping with our focus on performance, IVH Multi Select will paginate your lists if you happen to have the ivh.pager module included as a dependency (v0.3.0 or greater).

This is not a hard dependency, if you do not include IVH Pager your lists will be displayed in full.

Tracking Selected IDs

We're using selection-model internally to manage selections. As a convenience we provide a filter, ivhMultiSelectCollect, to help convert these to arrays of IDs if that is more in keeping with your use case. Note that this behavior is only supported when using the multi-additive selection mode (the default).

<!--
  The array demo.selectedIds will be updated whenever an item is clicked on or
  the user hits the "All" or "None" buttons.
-->
<div ivh-multi-select
     ivh-multi-select-items="demo.items"
     selection-model-on-change="demo.selectedIds | ivhMultiSelectCollect:item">
</div>

<!--
  You may also provide an id attribute and selected attribute if needed.
-->
<div ivh-multi-select
     ivh-multi-select-items="demo.items"
     selection-model-on-change="demo.selectedIds | ivhMultiSelectCollect:item:'id':'selected'">
</div>

Server Side Paging

For times when it would be too expensive to keep the entire list of available options on the client side we provide a second directive which allows you to provide an item getter function.

<div ivh-multi-select-async
    ivh-multi-select-fetcher="fetcher"
    ivh-multi-select-selected-items="mySelection"
    selection-model-mode="\'multi-additive\'">
  Blargus
</div>

Note the async in ivh-multi-select-async, this is in fact a separate directive from ivh-multi-select but supports a nearly identical set of attributes with the following exceptions:

  • The values assigned to ivh-multi-select-fetcher is required and expected to be a function (signiture detailed below).
  • The value assigned to ivh-multi-select-id-attribute will be used to compare newly fetched items with those in your selected items array as they are paged in and out. This is optional and defaults to 'id'.
  • ivh-multi-select-items is ignored... getting our items from the server is kinda the point.
  • You may use the ivh-multi-select-selected-items attribute to provide an array of selected items. This will be kept up to date with user driven changes as items are selected and deselected. Note that only 'single' and 'multi-additive' (the default) selection modes are supported. Order and item reference preservation is not guarenteed.

ivh-multi-select-fetcher

The function we'll use to fetch pages of items.

This should accept an options object with the following properties:

  • filter: A string, whatever the user has entered in the filter box
  • page: The zero-based page number we're requesting for paginated results.
  • pageSize: The number of items we expect per page

The function should return an object, or promise which resolves to shuch an object, with the following properties:

  • items: A page of collection items, if more than one page was returned only the first pageSize will be displayed (assuming paging is enabled).
  • page: [Optional] The zero-based page number corresponding to the returned results. If ommitted and paging is enabled we will assume page from the request options.
  • pageSize: The size of a page of results, if omitted we will assume pageSize from the request options.
  • totalCount: The total (unpaged) result set count

Autofocus Input fields

Include the IVH Auto Focus module in your application to enable auto-focusing multi select inputs.

Install with bower:

bower install --save angular-ivh-auto-focus

Include in your application

angular.module('myApp', [
  'ivh.multiSelect',
  'ivh.autoFocus'
]);

Enjoy auto focusing multi select inputs 😄.

Testing

Use npm test to run the full suite of linting, style checks, and unit tests.

Or, run each individually:

  • Use grunt jshint for linting
  • Use grunt jscs for coding style checks
  • Use grunt jasmine to unit tests

For ease of development the grunt watch task will run each of the above as needed when you make changes to source files.

Changelog

  • 2015-10-26 v0.8.0 (sync) Filter on calculated label
  • 2015-10-26 v0.6.0 Add support for server side paging
  • 2015-10-26 v0.5.0 Add custom label expressions
  • 2015-10-20 v0.2.0 Forward selection-model-on-change
  • 2015-10-08 v0.2.0 Forward options to selection model
  • 2015-10-07 v0.1.0 Initial release

License

MIT

About

A simple and performant multi select component for AngularJS apps

Resources

License

Stars

Watchers

Forks

Packages

No packages published