Active Admin - обновить второй выпадающий список на основе первого выпадающего списка, Ruby on Rails - PullRequest
14 голосов
/ 06 марта 2012

Я использую Active Admin Gem на Ruby on Rails. У меня есть форма, в которой я выбрал категорию и подкатегорию, а затем, соответственно, я должен заполнить данные. Итак, я создал две таблицы в sqlite, добавленные в активное административное решение.

Все работает нормально, но выпадающий список подкатегории не фильтруется в зависимости от выбранной категории.

Я новичок в Ruby и RoR тоже. Я не знаю, как обновить выпадающий список подкатегории после выбора категории.

Я знаю, что могу сделать это из AJAX и javascript, но я не знаю, где это написать?

Кроме того, есть ли какой-либо специальный фильтр, доступный в Active Admin, который сделает это без ajax или javascript.

Любые идеи или помощь будут высоко оценены.

Ответы [ 5 ]

18 голосов
/ 22 июля 2012

Я не знаю, существует ли какой-либо конкретный фильтр, доступный в Active Admin, но я решил его в 3 этапа (предполагая, что категория - это дом, подкатегория - это квартира):

1-й шаг: определить помощника, содержащего ajax-запрос

(конечно, вы должны предварительно определить path в rout.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-й шаг: добавить этот метод для: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-й шаг: отрисовать результат фильтрации

(вы можете сделать частичный рендеринг вместо :text, я решил оставить его в одном файле ресурсов activeadmin)

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
12 голосов
/ 16 января 2014

Я выполнил это, как любой другой разработчик, не работающий над рельсами, - быстро и грязно.Вот как:

#...
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}]
}
#...

AJAX не требуется.Обратите внимание, что это не удаляет нежелательные параметры, а просто отключает их (достаточно для моего сценария).Это можно легко сделать модульным с помощью помощника, но мне действительно нужна была функциональность только один раз.

6 голосов
/ 16 июля 2013

Для всех, кто борется с той же проблемой, посмотрите на это railscast

Я столкнулся с той же проблемой здесь

вот как я реализовалнесколько меню динамического выбора в 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()

перезапустите сервер, и меню заработает!

1 голос
/ 30 января 2018

Вы также можете использовать activeadmin_addons драгоценный камень Вложенный выбор

1 голос
/ 14 июля 2016

Теперь возможно с этим драгоценным камнем https://github.com/holyketzer/activeadmin-ajax_filter, использовать в вашей форме код, подобный этому:

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' 
}

А на вашей странице ресурса подкатегории:

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

не забудьте включить активы

...