AutoSelect2

Gem provide API (scripts, helpers, controller and base class for ajax-search) for initialize different select2 elements: static, ajax and multi-ajax.

The AutoSelect2 based on select2-rails gem.

Gem Version

Installation

First

Install select2-rails and include javascript and stylesheet assets as described on select2-rails page.

Second

Add this line to your application's Gemfile:

gem 'auto_select2'

And then execute:

$ bundle

Third

Select one of ways to include js in pipeline. Ways described below in section Javascript include variants

Fourth

Check controller and route collation. Gem contain controller Select2AutocompletesController and route

get 'select2_autocompletes/:class_name'

Fifth

Prepare folder app/select2_search_adapter if you want to use ajax-select2. This folder needed for storage custom SearchAdapter.

Compatibility

Gem tested and works in Rails 3.2 and Rails 4.0. You can test compatibility with other versions by yourself.

Easiest way to use

Use AutoSelect2Tag. It provide helpers:

  • select2_tag
  • select2_ajax_tag

and you can define select2 element like any other view elements in rails.

Example

You can find example project here.

Usage

Element types

Gem provides 3 types of select2 elements:

  • static
  • ajax
  • multi-ajax

For each of it exist javascript initializer. This is:

  • static_select2.js
  • ajax_select2.js
  • multi_ajax_select2_value_parser.js

Note: multi_ajax_select2_value_parser.js work only together with ajax_select2.js

Javascript include variants

You have two ways to include javascript files. First: in gem presents helper methods

  • static_select2_init_header_tags
  • ajax_select2_init_header_tags
  • ajax_multi_select2_init_header_tags

These helpers call javascript_include_tag and it is useful for initialize select2 scripts on a single page. Example of usage in a view:

- static_select2_init_header_tags

%div
  = select2_tag :my_select, my_options_for_select, class: 'small'

Second variant: include files in javascript assets. For this add the following to your app/assets/javascripts/application.js:

//= require auto_select2/static_select2
//= require auto_select2/ajax_select2
//= require auto_select2/multi_ajax_select2_value_parser

Select2 options

If you want to specify any parameters for select2 constructor you can pass it as hash into data-attribute s2options. This parameter handle most options but you can't pass through js-functions.

Static select2 usage

For initialize static select2 you must set auto-static-select2 css-class for select element:

= select_tag :my_select, my_options_for_select, class: 'my-class auto-static-select2'

Ajax select2 usage

For initialize ajax select 2 you must set auto-ajax-select2 css-class for hidden-input element. Then you have two ways. Easy way for simple selection: specify default_class_name, default_text_column and default_id_column as params for :href within data-attribute s2options (look at the end of this section). Other way for custom selection: create SearchAdapter. This adapter has following requirements:

  • class must be inherited from AutoSelect2::Select2SearchAdapter::Base
  • file must be put in folder app/select2_search_adapter
  • name of a adapter class must end with SearchAdapter
  • must has function search_default(term, page, options) (description of the function and return value goes below)

Returned value of search_default function must be follow:

  • if options contain :init key function must return hash {text: 'displayed text', id: 'id_of_initial_element'}
  • otherwise function must return the follow hash:

    { items: [ { text: 'first element', id: 'first_id' }, { text: 'second element', id: 'second_id' } ], total: count }

Here in total must be specified amount of all select variants. For example you have select element with 42 variants. Function search_default return part of it in items and in total each time you must set 42.

TIP: in search_default you can use functions from AutoSelect2::Select2SearchAdapter::Base:

  • default_finder(searched_class, term, options)
  • default_count(searched_class, term, options = {})
  • get_init_values(searched_class, ids, title_method=nil)

More about this function you can find in example project, in example below and in source code.

Finally hidden-input must has :href parameter in data-attribute s2options. This parameter specify url for ajax load select options. You can use helper

select2_autocompletes_path(class_name: :my_class_name)

or

select2_autocompletes_path(default_class_name: my_class,
                           default_text_column: :name,
                           default_id_column: :id)

Example of minimalistic SearchAdapter

class SystemRoleSearchAdapter < AutoSelect2::Select2SearchAdapter::Base
  class << self
    def search_default(term, page, options)
      if options[:init].nil?
        roles = default_finder(SystemRole, term, page: page)
        count = default_count(SystemRole, term)
        {
          items: roles.map do |role|
            { text: role.name, id: role.id.to_s } # here is optional parameter 'class_name'
          end,
          total: count
        }
      else
        get_init_values(SystemRole, options[:item_ids])
      end
    end
  end
end

More about SearchAdapter

SearchAdapter has some additional functions. First, you can define multiple search functions in one adapter. For example in adapter for User you want to find among all users, find users only in one department and so on. For this purpose define methods like

def search_unusual_case(term, page, options)
  # must has same behavior as search_default
end

near the search_default in SearchAdapter. Requirement for non-default search methods:

  • it must has same behavior as search_default
  • name of methods must start with search_

For use custom searcher specify it into :href within data-attribute s2options:

select2_autocompletes_path(class_name: MyClassName, search_method: :unusual_case)

Second, you may want to pass additional parameters in SearchAdapter. For example select options depend from another field on page. For this purpose you can specify

additional_ajax_data: {selector: 'input.css-class'}

inside data-attribute s2options. In this case in options of SearchAdapter appear additional values. It construct from name and value of html-elements. Example:

= hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@', class: 'add-to-select2'
= hidden_field_tag 'select2element', '',
                    class: 'auto-ajax-select2',
                    data: {s2options: { href: select2_autocompletes_path(class_name: :adapter_name,
                                                                         search_method: :unusual_case),
                                        additional_ajax_data: {selector: '.add-to-select2'}}}

Here we initialize ajax select2 and during load select variants in SearchAdapter options hash appear key :token with value 'VUBJKB23UIVI1UU1VOBVI@'.

Third, in hash with items from search method exist additional optional parameter class_name. This parameter specify css-class for result element in select2. It useful for show different icons for different select variants.

Multi ajax select2 usage

This feature require absolutely same things as ajax select2. Additionally you must add multiple css-class for input element, doesn't forget about multi_ajax_select2_value_parser.js script and pass multiple: true into data-attribute s2options.

Different multi ajax select2

Honestly speaking you can just pass multiple: true into data-attribute s2options and ajax-select2 become multiple. But in this case selected options from select2 become as comma separated string. As opposed to it multi_ajax_select2_value_parser.js make array of multiple ids. This is more comfortable for use in controller.

Initializing

Scripts automatically initialize on $(document).ready() and after ajaxSuccess. Moreover script handle cocoon events and run on cocoon:after-insert. If you for any reasons want to manually initializing select2, you can call initAutoAjaxSelect2() and/or initAutoStaticSelect2().

Contributing

  1. Fork it ( http://github.com/Loriowar/auto_select2/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request