Skip to content

How to: Populate a select dynamically

Sébastien Carceles edited this page Aug 14, 2019 · 1 revision

Problem

When you need to populate a select with a large data set, the form may take forever to show and / or you may hit a time out.

Thanks to select2, the best way to solve that issue is to populate the select dynamically.

Implementation

Let's say you have a Venue model which belongs_to :city.

Initialize the select2 in trestle/custom.js:

$(function() {
  $("#venue_city_id").select2({
    theme: 'bootstrap',
    allowClear: true,
    minimumInputLength: 3,
    containerCssClass: ':all:',
    dataType: 'json',
    ajax: {
      url: '/admin/venues/cities',
      delay: 250,
      data: function(params) {
        return { q: params.term }
      },
      processResults: function (data, params) {
        return {
          results: $.map(data, function(value, index) {
            return { id: value.id, text: value.text };
          })
        };
      }
    }
  });
});

In the venues_admin.rb file:

Trestle.resource(:venues) do
  menu :venues, icon: "fa fa-building", group: :data

  table do
    column :name
    column :city, -> (venue) { venue.city.name }
    actions
  end

  form do |venue|
    text_field :name
    select :city_id, City.where(id: venue.city_id)
  end

  controller do
    def cities
      if params[:q]
        # Request your data here and return a collection of id / text items, which will be used by the select2 component
        render json: City.where("name like ?", "#{params[:q]}%").collect { |city| { id: city.id, text: city.name } }
      else
        render json: []
      end
    end
  end

  routes do
    get :cities, on: :collection
  end
end