Skip to content

dependent select boxes

zorec edited this page Dec 13, 2013 · 14 revisions

You can easily set dependent select boxes.

For instance, if you have Project resource and Task resource with "project has_many tasks" association. And you need to have select box within Project form for choosing tasks from the particular choosen project.

    edit do
      field :project
      field :tasks do
        param = "f[project_id_eq]"
        options_source_params do
          { param => bindings[:object].try(:project_id) || -1 }
        end
        html_attributes do
          { data: { "dependant-filteringselect" => "field=project_id", "dependant-param" => param } }
        end
      end
    end

List of options for select boxes is obtained by ajax call to options action. By customizing options method in controller or redefining remote-source attribute you can easily configure the list of options.

For example you need to set default task in the example above:

    def options
      if params[:f].try(:[], :id_eq).to_i == -1 
        authorize!(action_name.to_sym, resource_class) # CanCan
        # or use any other model method
        task = Task.default_task(params[:f][:project_id_eq])
        options!(collection: [task].compact)
      else
        options!
      end
    end

Maybe you want to set the both fields on the same line. It can be done in the view. Snippet below shows all settings in the view (file views/<RESOURCE>/_edit.html.haml:

- edit_form.configure do |form|
  - f1 = form.field :project do |f1|
    - f1.options_source = options_task_categories_path
    - f1.html_attributes = { class: 'span3' }

  - f2 = form.default_group.field :task do |f2| 
    - param = "f[project_id_eq]"
    - f2.options_source_params = { param => edit_form.resource.project.try(:id) }
    - f2.html_attributes = { class: 'span3', data: { "dependant-filteringselect" => "#item_project", "dependant-param" => param } }

    - f2.content do
      = form.input :task, label: f1.label, required: f2.required? do
        = form.render_filteringselect f1
        = form.render_filteringselect f2

= form_render edit_form

In case you need set dependent select boxes in html/haml you need to fill params as show example below:

    %input{class: "input-medium span3", type: "text", name: "value[project]".html_safe, value: project_id.to_s,
      data: { filteringselect: true, options: {placeholder: I18n.t('admin.misc.search'), remote_source: options_projects_path, init: { project_id.to_s => task.project.to_label} }.to_json}}
    - param = "f[project_id_eq]"
    %input{id: 'change_task_select', class: "input-medium span4", type: "text", name: 'value[task]'.html_safe, value: task.id,
      data: { filteringselect: true,
        options: %Q{{"placeholder":"#{I18n.t('admin.misc.search')}","remote_source":"#{options_tasks_path}","remote_source_params":{"#{param}":#{project_id}}}}.html_safe,
        init: { task.id.to_s => task.to_label},
        "dependant-filteringselect" => "field=project", "dependant-param" => param }}

For more see class Lepidlo.Form.Plugins.DependantFilteringSelect in app/assets/javascripts/lepidlo/forms.coffee

Clone this wiki locally