Active Admin - refresh second drop down based on f

2019-01-22 09:04发布

I am using Active Admin Gem on Ruby on Rails. I have a form in which i have selected category and sub category and then accordingly i have to fill the data. So i created two tables in sqlite added in active admin resouce.

Every thing is working fine but the drop down of sub category is not getting filtered based on the category choosen.

I am new to Ruby and RoR too. I don't know how to refresh dropdown of the subcategory after selecting category.

I know i can do it from AJAX and javascript but i dont know where to code for that?

Also, is there any specific filter avaliable in Active Admin which will make it happen without ajax or javascript.

Any ideas or help will be highly appreciated.

5条回答
欢心
2楼-- · 2019-01-22 09:09

For anyone else wrestling with the same problem, look at this railscast

I faced the same problem here

here's how I implemented multiple dynamic select menus in activeadmin:

config/initializers/active_admin.rb

  config.register_javascript 'exam_registrations.js.coffee'

app/admin/exam_registrations.rb

  form do |f|
    f.inputs "Exam Registration Details" do
      f.input :user_id, :label => 'Teacher', :as => :select, :collection => User.where(:admin => 'false', :active => true).order(:name), :include_blank => true
      f.input :student_id, :hint => 'Students grouped by teacher names', :as => :select, :collection => option_groups_from_collection_for_select(User.where(:admin => false, :active => true).order(:name), :students, :name, :id, :name)
      f.input :lesson_id, :hint => 'Lessons grouped by student names', :as => :select, :collection => option_groups_from_collection_for_select(Student.where(:active => true).order(:name), :lessons, :name, :id, :name)
    end
    f.buttons
  end

app/assets/javascripts/exam_registrations.js.coffee

#first menu    
jQuery ->
      $('#exam_registration_student_id').parent().hide()
      students = $('#exam_registration_student_id').html()
      $('#exam_registration_user_id').change ->
        user = $('#exam_registration_user_id :selected').text()
        escaped_user = user.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1')
        options = $(students).filter("optgroup[label='#{escaped_user}']").html()
        if options
          $('#exam_registration_student_id').html(options)
          $('#exam_registration_student_id').parent().show()
        else
          $('#exam_registration_student_id').empty()
          $('#exam_registration_lesson_id').empty()

# second menu
  $('#exam_registration_lesson_id').parent().hide()
  lessons = $('#exam_registration_lesson_id').html()
  $('#exam_registration_student_id').click ->
    student = $('#exam_registration_student_id :selected').text()
    escaped_student = student.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1')
    options = $(lessons).filter("optgroup[label='#{escaped_student}']").html()
    if options
      $('#exam_registration_lesson_id').html(options)
      $('#exam_registration_lesson_id').parent().show()
    else
      $('#exam_registration_lesson_id').empty()

restart the server and the menus work!

查看更多
Anthone
3楼-- · 2019-01-22 09:18

I accomplished this as any non-rails developer working on a rails project would - quick and dirty. Here's how:

#...
f.input :user, :input_html => {
  :onchange => "
    var user = $(this).val();

    $('#order_location_id').val(0).find('option').each(function(){
      var $option = $(this),
        isCorrectUser = ($option.attr('data-user') === user);  

        $option.prop('disabled',!isCorrectUser);
    });
  "
}
f.input :location, collection: Location.all.map{ |loc|
  [loc.name,loc.id, {"data-user" => loc.user_id}]
}
#...

No AJAX required. Note that this does not remove the unwanted options, it just disables them (sufficient for my scenario). This could easily be made modular with a helper, but I really only needed the functionality once.

查看更多
可以哭但决不认输i
4楼-- · 2019-01-22 09:21

You can also use activeadmin_addons gem Nested Select

查看更多
别忘想泡老子
5楼-- · 2019-01-22 09:26

Now it's possible with this gem https://github.com/holyketzer/activeadmin-ajax_filter, use in you form code like this:

f.input :category_id, as: :select # ...
f.input :subcategory_id, as: :ajax_select, data: { 
  ajax_search_fields: [:category_id], 
  search_fields: [:subcategory_atrribute], 
  url: '/admin/subcategories/filter' 
}

And in you subcategory resource page:

ActiveAdmin.register Subcategory do
  include ActiveAdmin::AjaxFilter
  # ...
end

don't forget to include assets

查看更多
唯我独甜
6楼-- · 2019-01-22 09:32

i don't know if there is any specific filter avaliable in Active Admin, but i solved it in this 3-steps way (assuming category - is a house, subcategory - is a flat):

1-st step: define helper containing ajax request

(of course, you have to predefine path in routes.rb)

#application_helper.rb
def remote_request(type, path, params={}, target_tag_id)
  "$.#{type}('#{path}',
             {#{params.collect { |p| "#{p[0]}: #{p[1]}" }.join(", ")}},
             function(data) {$('##{target_tag_id}').html(data);}
   );"
end

2-nd step: add this method for :onchange action

#admin/inhabitants.rb (DSL with formtastic)

form do |f|
  f.inputs do
  #...
    f.input :house, :input_html => {
        :onchange => remote_request(:post, :change_flats, {:house_id=>"$('#house_id').val()"}, :flat_id)
    }
    f.input :flat
  #...
  end
end

3-rd step: render result of filtering

(you can render partial instead of :text, I decided leave it in one activeadmin resource file )

controller do
  def change_flats
    @flats = House.find_by_id(params[:house_id]).try(:flats)
    render :text=>view_context.options_from_collection_for_select(@flats, :id, :flat_number)
  end
end
查看更多
登录 后发表回答