Picker

    Picker is a powerful component that allows you to create custom overlay pickers which looks like iOS native picker.

    Picker could be used as inline component or as overlay. Overlay Picker will be automatically converted to Popover on tablets (iPad).

    Picker App Methods

    Let's look at related App methods to work with Picker:

    app.picker.create(parameters)- create Picker instance

    • parameters - object. Object with picker parameters

    Method returns created Picker's instance

    app.picker.destroy(el)- destroy Picker instance

    • el - HTMLElement or string (with CSS Selector) or object. Picker element or Picker instance to destroy.

    app.picker.get(el)- get Picker instance by HTML element

    • el - HTMLElement or string (with CSS Selector). Picker element.

    Method returns Picker's instance

    app.picker.close(el)- close Picker

    • el - HTMLElement or string (with CSS Selector). Picker element to close.

    Method returns Picker's instance

    For example:

    var picker = app.picker.create({
      inputEl: '#picker-input',
      cols: [
         {
           values: ['apple', 'orange', 'bananna'],
           displayValues: ['Apple', 'Orange', 'Bananna'],
         }
       ]
    });

    Picker Parameters

    Let's look on list of all available Picker parameters:

    Parameter Type Default Description
    rotateEffect boolean false Enables 3D rotate effect
    momentumRatio number 7 Larger values produces more momentum when you release picker after fast touch and move
    updateValuesOnMomentum boolean false Updates picker and input values during momentum
    updateValuesOnTouchmove boolean true Updates picker and input values during touch move
    freeMode boolean false Disables snapping on values
    value array Array with initial values. Each array item represents value of related column
    formatValue function (values, displayValues) Function to format input value, should return new/formatted string value. values and displayValues are arrays where each item represents value/display value of related column
    cols array Array with columns. Each array item represents object with column parameters
    Container/opener-specific parameters
    containerEl string
    HTMLElement
    String with CSS selector or HTMLElement where to place generated Picker HTML. Use only for inline picker
    openIn string auto Can be auto, popover (to open picker in popover), sheet (to open in sheet modal). In case of auto will open in sheet modal on small screens and in popover on large screens.
    inputEl string or HTMLElement String with CSS selector or HTMLElement with related input element
    scrollToInput boolean true Scroll viewport (page-content) to input when picker opened
    inputReadOnly boolean true Sets "readonly" attribute on specified input
    cssClass string Additional CSS class name to be set on picker element
    closeByOutsideClick boolean true If enabled, picker will be closed by clicking outside of picker or related input element
    toolbar boolean true Enables picker toolbar
    toolbarCloseText string Done Text for Done/Close toolbar button
    routableModals boolean true Will add opened picker to router history which gives ability to close picker by going back in router history and set current route to the picker modal
    url string select/ Picker modal URL that will be set as a current route
    view object View where to set routing when routableModals enabled. Defaults to parent view of inputEl or main view if not found parent view
    Render Functions
    renderToolbar function Function to render toolbar. Must return toolbar HTML string
    render function Function to render whole picker. Must return picker full HTML string
    Events
    on object Object with events handlers. For example:
    var picker = app.picker.create({
      ...
      on: {
        opened: function () {
          console.log('Picker opened')
        }
      }
    })

    Note that all following parameters can be used in global app parameters under picker property to set defaults for all pickers. For example:

    var app = new Framework7({
      picker: {
        rotateEffect: true,
        openIn: 'popover',
      }
    });

    Column Parameters

    When we configure Picker we need to pass cols parameter. It is an array where each item is an object with column parameters:

    Parameter Type Default Description
    values array Array with string columns values
    displayValues array Array with string columns values that will be displayed in Picker. If not specified, it will display values from values parameter
    cssClass string Additional CSS class name to be set on column HTML container
    textAlign string Text alignment of column values, could be "left", "center" or "right"
    width number Column width in px. Useful if you need to fix column widths in picker with dependent columns. By default, calculated automatically
    divider boolean false Defines column that should be used as a visual divider, that doesn't have any values
    content string Should be specified for divider-column (divider:true) with content of the column
    onChange function(picker, value, displayValue) Callback function that will be executed when picker value changed.

    Picker Methods & Properties

    After we initialize Picker we have its initialized instance in variable (like picker variable in examples above) with helpful methods and properties:

    Properties
    picker.app Link to global app instance
    picker.containerEl Picker wrapping container HTML element (when inline picker is in use)
    picker.$containerEl Dom7 instance with picker wrapping container HTML element (when inline picker is in use)
    picker.el Picker HTML element
    picker.$el Dom7 instance with picker HTML element
    picker.inputEl Picker input HTML element (passed in inputEl parameter)
    picker.$inputEl Dom7 instance with picker input HTML element (passed in inputEl parameter)
    picker.value Array where each item represents current selected value for each column
    picker.cols Array with specified Picker columns. Each column also has its own methods and properties (look below)
    picker.opened true if Picker is currently opened
    picker.inline true when inline picker is in use
    picker.url Picker URL (that was passed in url parameter)
    picker.view Picker View (that was passed in view parameter) or found parent view
    picker.params Object with initialization parameters
    Methods
    picker.setValue(values, duration) Set new picker value. values is array where each item represents value for each column. duration - transition duration in ms
    picker.getValue() Returns current picker value
    picker.addValue() Adds value to the values array. Useful in case if multiple selection is enabled (with multiple: true parameter)
    picker.open() Open Picker
    picker.close() Close Picker
    picker.destroy() Destroy Picker instance and remove all events
    picker.on(event, handler) Add event handler
    picker.once(event, handler) Add event handler that will be removed after it was fired
    picker.off(event, handler) Remove event handler
    picker.off(event) Remove all handlers for specified event
    picker.emit(event, ...args) Fire event on instance

    Column Methods & Properties

    Each column in picker.cols array also has its own useful methods and properties.

    //Get first column
    var col = picker.cols[0];
    
    Properties
    col.el Column HTML element
    col.$el Dom7 instance with column HTML container
    col.items Dom7 instance with column items HTML elements
    col.value Currently selected column value
    col.displayValue Currently selected column display value
    col.activeIndex Index number of currently selected/active item
    Methods
    col.setValue(value, duration) Set new value for current column. value is a new value, duration - transition duration in ms
    col.replaceValues(values, displayValues) Replace column values and displayValues with new ones

    Picker Events

    Picker will fire the following DOM events on picker element and events on app and picker instance:

    DOM Events

    Event Target Description
    picker:open Picker Element<div class="picker"> Event will be triggered when Picker starts its opening animation
    picker:opened Picker Element<div class="picker"> Event will be triggered after Picker completes its opening animation
    picker:close Picker Element<div class="picker"> Event will be triggered when Picker starts its closing animation
    picker:closed Picker Element<div class="picker"> Event will be triggered after Picker completes its closing animation

    App and Picker Instance Events

    Picker instance emits events on both self instance and app instance. App instance events has same names prefixed with picker.

    Event Target Arguments Description
    change picker (picker, value, displayValue) Event will be triggered when picker value changes
    pickerChange app
    init picker (picker) Event will be triggered when picker initialized
    pickerInit app
    open picker (picker) Event will be triggered when Picker starts its opening animation. As an argument event handler receives picker instance
    pickerOpen app
    opened picker (picker) Event will be triggered after Picker completes its opening animation. As an argument event handler receives picker instance
    pickerOpened app
    close picker (picker) Event will be triggered when Picker starts its closing animation. As an argument event handler receives picker instance
    pickerClose app
    closed picker (picker) Event will be triggered after Picker completes its closing animation. As an argument event handler receives picker instance
    pickerClosed app
    beforeDestroy picker (picker) Event will be triggered right before Picker instance will be destroyed. As an argument event handler receives picker instance
    pickerBeforeDestroy app

    Examples

    Picker With Single Value

    <div class="block-title">Picker with single value</div>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-input-wrap">
                <input type="text" placeholder="Your iOS device" readonly="readonly" id="demo-picker-device"/>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    var pickerDevice = app.picker.create({
      inputEl: '#demo-picker-device',
      cols: [
        {
          textAlign: 'center',
          values: ['iPhone 4', 'iPhone 4S', 'iPhone 5', 'iPhone 5S', 'iPhone 6', 'iPhone 6 Plus', 'iPad 2', 'iPad Retina', 'iPad Air', 'iPad mini', 'iPad mini 2', 'iPad mini 3']
        }
      ]
    });
    

    Two Values and 3D-Rotate Effect

    <div class="block-title">2 values and 3d-rotate effect</div>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-input-wrap">
                <input type="text" placeholder="Describe yourself" readonly="readonly" id="demo-picker-describe"/>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    var pickerDescribe = app.picker.create({
      inputEl: '#demo-picker-describe',
        rotateEffect: true,
        cols: [
          {
            textAlign: 'left',
            values: ('Super Amazing Bat Iron Rocket Lex Beautiful Wonderful Raining Happy Funny Cool Hot').split(' ')
          },
          {
            values: ('Man Luthor Woman Boy Girl Person Cutie Babe Raccoon').split(' ')
          },
        ]
    });
    

    Dependent Values

    <div class="block-title">Dependent values</div>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-input-wrap">
                <input type="text" placeholder="Your car" readonly="readonly" id="demo-picker-dependent"/>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    
    var carVendors = {
      Japanese : ['Honda', 'Lexus', 'Mazda', 'Nissan', 'Toyota'],
      German : ['Audi', 'BMW', 'Mercedes', 'Volkswagen', 'Volvo'],
      American : ['Cadillac', 'Chrysler', 'Dodge', 'Ford']
    };
    var pickerDependent = app.picker.create({
      inputEl: '#demo-picker-dependent',
      rotateEffect: true,
      formatValue: function (values) {
        return values[1];
      },
      cols: [
        {
          textAlign: 'left',
          values: ['Japanese', 'German', 'American'],
          onChange: function (picker, country) {
            if(picker.cols[1].replaceValues){
              picker.cols[1].replaceValues(carVendors[country]);
            }
          }
        },
        {
          values: carVendors.Japanese,
          width: 160,
        },
      ]
    });
    

    Custom toolbar

    <div class="block-title">Custom toolbar</div>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-input-wrap">
                <input type="text" placeholder="Describe yourself" readonly="readonly" id="demo-picker-custom-toolbar"/>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    
    var pickerCustomToolbar = app.picker.create({
      inputEl: '#demo-picker-custom-toolbar',
      rotateEffect: true,
      renderToolbar: function () {
        return '<div class="toolbar">' +
          '<div class="toolbar-inner">' +
            '<div class="left">' +
              '<a href="#" class="link toolbar-randomize-link">Randomize</a>' +
            '</div>' +
            '<div class="right">' +
              '<a href="#" class="link sheet-close popover-close">That\'s me</a>' +
            '</div>' +
          '</div>' +
        '</div>';
      },
      cols: [
        {
          values: ['Mr', 'Ms'],
        },
        {
          textAlign: 'left',
          values: ('Super Amazing Bat Iron Rocket Lex Beautiful Wonderful Raining Happy Funny Cool Hot').split(' ')
        },
        {
          values: ('Man Luthor Woman Boy Girl Person Cutie Babe Raccoon').split(' ')
        },
      ],
      on: {
        open: function (picker) {
          picker.$el.find('.toolbar-randomize-link').on('click', function () {
            var col0Values = picker.cols[0].values;
            var col0Random = col0Values[Math.floor(Math.random() * col0Values.length)];
    
            var col1Values = picker.cols[1].values;
            var col1Random = col1Values[Math.floor(Math.random() * col1Values.length)];
    
            var col2Values = picker.cols[2].values;
            var col2Random = col2Values[Math.floor(Math.random() * col2Values.length)];
    
            picker.setValue([col0Random, col1Random, col2Random]);
          });
        },
      }
    });
    

    Inline Picker / Date-time

    <div class="block-title">Inline Picker / Date-time</div>
    <div class="list no-margin">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-input-wrap">
                <input type="text" placeholder="Date Time" readonly="readonly" id="demo-picker-date"/>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="block block-strong no-padding no-margin margin-bottom">
      <div id="demo-picker-date-container"></div>
    </div>
    
    var today = new Date();
    var pickerInline = app.picker.create({
      containerEl: '#demo-picker-date-container',
      inputEl: '#demo-picker-date',
      toolbar: false,
      rotateEffect: true,
      value: [
        today.getMonth(),
        today.getDate(),
        today.getFullYear(),
        today.getHours(),
        today.getMinutes() < 10 ? '0' + today.getMinutes() : today.getMinutes()
      ],
      formatValue: function (values, displayValues) {
        return displayValues[0] + ' ' + values[1] + ', ' + values[2] + ' ' + values[3] + ':' + values[4];
      },
      cols: [
        // Months
        {
          values: ('0 1 2 3 4 5 6 7 8 9 10 11').split(' '),
          displayValues: ('January February March April May June July August September October November December').split(' '),
          textAlign: 'left'
        },
        // Days
        {
          values: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        },
        // Years
        {
          values: (function () {
            var arr = [];
            for (var i = 1950; i <= 2030; i++) { arr.push(i); }
              return arr;
          })(),
        },
        // Space divider
        {
          divider: true,
          content: '&nbsp;&nbsp;'
        },
        // Hours
        {
          values: (function () {
            var arr = [];
            for (var i = 0; i <= 23; i++) { arr.push(i); }
              return arr;
          })(),
        },
        // Divider
        {
          divider: true,
          content: ':'
        },
        // Minutes
        {
          values: (function () {
            var arr = [];
            for (var i = 0; i <= 59; i++) { arr.push(i < 10 ? '0' + i : i); }
              return arr;
          })(),
        }
      ],
      on: {
        change: function (picker, values, displayValues) {
          var daysInMonth = new Date(picker.value[2], picker.value[0]*1 + 1, 0).getDate();
          if (values[1] > daysInMonth) {
            picker.cols[1].setValue(daysInMonth);
          }
        },
      }
    });