vue-awesome-picker

A Vue.js Picker Component
2,130 126
Install
npm install vue-awesome-picker
Latest Version:2.1.0
Vue:2
License:MIT
Last Updated:Oct 17, 2026
Links: GitHub  ·  npm
Maintainer: fyerl

vue-awesome-picker NPM Version NPM Downloads

A mobile picker component built with Vue.js and BetterScroll.

This is a Vue 2 component.
Recommended Vue version: vue@2.7.16 (or 2.7.x). Vue 3 is not supported.

Features

  • Supports single-column, multi-column, and cascade data
  • Built-in time and date picker modes
  • 3D wheel scrolling effect
  • Customizable title/text/colors

Demo

The demo enables Service Worker.

Installation

npm install vue-awesome-picker --save

Usage

// main.js
import AwesomePicker from 'vue-awesome-picker'

Vue.use(AwesomePicker)
<!-- See src/App.vue for a full example -->
<awesome-picker
  ref="picker"
  :data="picker.data"
  :anchor="picker.anchor"
  :textTitle="picker.textTitle"
  :textConfirm="picker.textConfirm"
  :textCancel="picker.textCancel"
  :colorTitle="picker.colorTitle"
  :colorConfirm="picker.colorConfirm"
  :colorCancel="picker.colorCancel"
  :swipeTime="picker.swipeTime"
  @cancel="handlePickerCancel"
  @confirm="handlePickerConfirm"
/>
methods: {
  show () {
    this.$refs.picker.show()
  }
}

Props

Prop Description Options Type Default
data See the data section below - Array []
anchor See the anchor section below - Array []
includeItem Include the original selected option as item in each change or confirm result - Boolean false
type Built-in picker type (no data required) date, time String -
textTitle Title text - String ''
textConfirm Confirm button text - String Confirm
textCancel Cancel button text - String Cancel
colorTitle Title color - String #000000
colorConfirm Confirm button color - String #42b983
colorCancel Cancel button color - String #999999
swipeTime Wheel swipe duration (better-scroll swipeTime) - Number 1800

data

vue-awesome-picker determines whether the picker is normal or cascade by data shape, so please follow one of the formats below.

Normal picker (single or multi-column): pass a two-dimensional array. Each option can be a primitive value or an object with a value field. Object options display only value; use includeItem to retrieve fields such as id on confirmation.

[
  ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],
  ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
]

Cascade picker: build hierarchy using children.

Each column follows the selected item in its parent column. Changing a parent resets all descendant columns to their first item. An empty or omitted children array ends the path, so confirm only contains the populated columns. Empty root data produces an empty selection ([]).

[
  {
    value: 'A',
    children: [
      { value: 'A-a' },
      { value: 'A-b' },
      { value: 'A-c' }
    ]
  },
  {
    value: 'B',
    children: [
      { value: 'B-a' },
      { value: 'B-b' }
    ]
  }
]
Changing the number of columns

Replace data to add or remove columns, including while the picker is open. For normal data, change the number of inner arrays. For cascade data, change the children hierarchy. Supply an anchor for the new data to select its initial path.

For example, switch from a single cascade column to two columns and reopen:

// Previously: this.picker.data = [{ value: 'A' }, { value: 'B' }]
this.picker.data = ['A', 'B'].map(value => ({
  value,
  children: ['X', 'Y', 'Z'].map(child => ({ value: value + child }))
}))
this.picker.anchor = [1, 2] // Selects B and BZ
this.$nextTick(() => this.$refs.picker.show())

Wait for Vue to pass updated props to the component before calling show().

anchor

anchor controls the default selected item for each wheel when the picker opens. It supports two formats. If no match is found, index 0 is selected.

Recommended object array format (same shape as the confirm event payload).
When both index and value exist, index has higher priority.

Cascade anchors are resolved from parent to child. Each index must exist in the selected parent's children; an out-of-range index falls back to 0 at that level. When an anchor object only supplies value, that value is matched within the selected parent's children.

[
  { index: 0, value: 'A' },
  { index: 0, value: 'A-a' }
]

Index array format:

[0, 0]

Scrolling changes the temporary selection. Clicking Cancel or the outside mask discards those changes: reopening restores the selection from when that opening began, including the initial anchor or a selection confirmed on a previous opening. Cancellation does not emit confirm or modify the anchor prop. Replacing data or reactively updating anchor starts a new selection using the supplied anchor. An anchor update also applies while the picker is open and becomes the new cancellation baseline. It does not emit confirm.

Choosing the built-in date

Use anchor with type="date"; custom date data is not required. Date values include the Y, M, and D suffixes, with years from 1900 through 2100:

<awesome-picker ref="datePicker" type="date" :anchor="dateAnchor" />
data () {
  return { dateAnchor: [] }
},
methods: {
  showDate (year, month, day) {
    this.dateAnchor = [
      { value: `${year}Y` },
      { value: `${month}M` },
      { value: `${day}D` }
    ]
    this.$nextTick(() => this.$refs.datePicker.show())
  }
}

For example, showDate(2024, 2, 29) opens at February 29, 2024, even after a previous confirmation or cancellation. The equivalent zero-based index anchor is [124, 1, 28]. Setting anchor to [] restores the built-in default date. Replace the anchor array as above, or use Vue 2 reactive mutations to edit it.

Methods

Method Description
show Open the picker

Events

Event Description Payload
change A visible selection changes after scrolling and cascade synchronization finish Same shape as confirm, including optional item
confirm Triggered after clicking the confirm button [{ index, value }, ...]; with includeItem: [{ index, value, item }, ...]
cancel Triggered after clicking the cancel button or the mask outside the picker -

Previewing a selection before confirmation

Listen to change for a temporary selection and confirm for the final choice. change fires after the wheels finish moving, not for every item passed during a swipe. Cascade changes contain the complete synchronized path. Concurrently moving columns settle before a preview is emitted, and unchanged selections are not emitted again.

Opening, reopening, updating data or anchor, and restoring a cancelled selection do not emit change. A new opening or external data/anchor update establishes a new comparison baseline. change does not close the picker, commit the selection, or change its cancellation behavior.

<awesome-picker
  ref="picker"
  :data="options"
  @change="onChange"
  @confirm="onConfirm"
  @cancel="onCancel"
/>
data () {
  return { options: [['A', 'B', 'C']], preview: [], saved: [] }
},
methods: {
  onChange (selection) {
    this.preview = selection
  },
  onConfirm (selection) {
    this.saved = selection
    this.preview = selection
  },
  onCancel () {
    this.preview = this.saved
  }
}

Cancellation restores the picker's opening selection. It cannot undo effects already applied by your change handler, so discard or restore the application's preview in cancel, as above. Use confirm for actions that should be committed.

Returning ids and custom fields

Enable includeItem to read the original option alongside its selected index and display value. The default remains false, preserving the existing confirmation payload. change also includes item when enabled. This works with both normal columns and cascade objects.

<awesome-picker ref="peoplePicker" :data="people" include-item @confirm="onConfirm" />
data () {
  return {
    people: [[
      { value: 'Alice', id: 42, department: 'Design' },
      { value: 'Bob', id: 73, department: 'Engineering' }
    ]]
  }
},
methods: {
  onConfirm (selection) {
    const { index, value, item } = selection[0]
    console.log(index, value, item.id, item.department)
  }
}

item references the original option, including its custom fields and any children; treat it as read-only. For primitive options, item is that primitive. Items follow the selected indices and cascade path, so duplicate display values can still return distinct ids. The picker does not merge custom fields into index or value, and does not add item unless includeItem is enabled.

Development

git clone git@github.com:Fyerl/vue-awesome-picker.git
cd vue-awesome-picker
npm install
npm run dev
npm run build

Run the regression tests with Node.js 20 or later:

npm run test:date
npx playwright install chromium webkit
npm run test:browser

Browser tests rebuild the library and demo, then exercise the library bundle in Chromium and WebKit.

Related Packages

vue-3-better-picker

Mobile picker component for Vue 3

68,823 0
@v-c/picker

picker ui component for vue

57,185 32
vuemoji-picker

Vue 2 and 3 lightweight emoji picker.

124,448 72
@invisiburu/vue-picker

A native-like select field, but better.

5,668 16
date-of-birth

date of birth

3,321 0

Version History

Version Released Vue License
2.1.0 ^2.6.14 || ^2.7.0 MIT
2.0.0 ^2.6.14 || ^2.7.0 MIT
1.1.0 ^2.5.11 MIT
1.0.6 ^2.5.11 MIT
1.0.5 ^2.5.11 MIT