Загрузить данные по select_tag

У меня есть стандартные модели электронной коммерции: ProductCategory, Product, Order а также OrderItem

В OrderItem модель есть product_id колонка. Когда пользователь создает заказ и добавляет новый элемент заказа, я хочу позволить ему сначала выбрать категорию продукта (в select_tag), а затем загрузить в f.collection_select :product_id только товары из этой категории.

Теперь мой _order_item_fields.html.haml выглядит так:

.form-group
  = label_tag 'product_category_id', 'Category'
  = select_tag 'product_category_id', options_for_select(ProductCategory.all, 'id', 'name')

.form-group
  = f.label :product_id, 'Product'
  = f.collection_select :product_id, {# now it's empty}, :id, :name, {prompt: 'Choose category first'}

Итак, мне нужно написать некоторую функцию JS для загрузки данных, основанных на выбранной категории. Я не уверен, если мне нужно написать def в orders_controller или я могу сделать в orders.coffee как функция вызывается выбрать из product_category_id тег.

Можете ли вы показать мне правильный путь?

Спасибо за любую помощь!

1 ответ

Решение

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

контроллер

# OrdersController

def product_options
  category_id = params[:category_id]

  render json: {
    products: ProductCategory.find(category_id).products.pluck(:id, :name)
  }
end

Это вернет JSON следующей формы:

{
  products: [
    [5, 'name of product with id 5'],
    [12, 'name of product with id 12'],
    ...
  ]
}

маршрутизация

Затем вам нужно добавить запись маршрута для этого:

# Routes
get '/route/to/product_options/:category_id', to: 'orders#product_options'

Я думаю, что у вас есть resources :orders в ваших маршрутах где-то, но для краткости я просто создал маршрут как этот сейчас - вы можете изменить его для ваших маршрутов!

Кофе

Чтобы получить этот JSON, вы можете использовать jquery:

# orders.coffee

category_id = 5
$.get("/route/to/product_options/#{category_id}")

Чтобы не было статики category_id Просто послушай change событие селектора вашей категории:

load_new_category = (category_id) ->
  $.get("/route/to/product_options/#{category_id}")

$ -> # wait until page is loaded completely 
  $('[name="product_category_id"]').on 'change', ->
    load_new_category $(@).val()

Наконец, вы должны сделать что-то с возвращенным json, чтобы построить ваши параметры:

set_product_options = (products_json) ->
  options_html = ''

  for product_array in products_json.products
    id = product_array[0]
    name = product_array[1]

    options_html += "<option value='#{id}'>#{name}</option>"

  $('[name="product_id"]').html options_html

load_new_category = (category_id) ->
  # attach it to `set_product_options` with `.done()`
  $.get("/route/to/product_options/#{category_id}").done set_product_options

$ ->
  $('[name="product_category_id"]').on 'change', ->
    load_new_category $(@).val()

Пожалуйста, дважды проверьте селекторы jquery в случае проблем (если rails действительно генерирует эти имена), но это должно дать вам хороший старт для реализации и оптимизации его под ваши нужды.

(Распечатал это с головы, так что надеюсь, что в нем нет опечаток.)

Другие вопросы по тегам