三个模型 Category, Tag, Product, Category 有多个 Tag,Tag 有多个 Product, 现在想编辑 Product 的时候, 选择 Category 的时候。让 Tag 随着改变。 这个应该怎么实现。这样表关联有什么问题的吗?
JS 的问题吧
将关联数据渲染成嵌套的 json,每次更新选择之后取到新的 category 的 id,再通过 category 的 id 取到对应的 tags 集合,更新到下一级的select控件。比如 controller 里边可以写:
select
# app/controllers/products_controller.rb class ProductsController < ApplicationController def edit @multi_level_products_hash = {} @categories = Category.all @tags_options = {} tags = @categories.map(&:tags).flatten tags.each do |tag| @tags_options[tag.id] = "<option value=#{tag.id}>#{tag.name}</option>" end @products_options = {} tags.map(&:products).flatten.each do |product| @products_options[product.id] = "<option value=#{product.id}>#{product.name}</option>" end @categories.each do |category| @multi_level_products_hash[category.id] = {} category.tags.each do |tag| @multi_level_products_hash[category.id][tag.id] = tag.products.map(&:id) end end end
view 层的代码片断
<!-- app/views/products/edit.html.erb --> <%= collection_select :category, :name, @categories, :id, :name %> <%= select_tag :tag %> <%= select_tag :product %> <%= javascript_tag do %> var multiLevelProducts = <%= raw @multi_level_products_hash.to_json %>; var tagsOptions = <%= raw @tags_options.to_json %> var productsOptions = <%= raw @products_options.to_json %> <% end %>
后边要做的事就是每次通过 category 的 idcategoryId取到对应的 tags 的 id 的集合,也就是multiLevelProducts[categoryId]的键集。tag 的处理跟 category 一致。
categoryId
multiLevelProducts[categoryId]
// app/assets/javascript/products.js $.extend({ keys: function(obj) { var a = []; $.each(obj, function(k) { a.push(k); }); return a; } }); $(document).ready(function() { $('#category_name').on('change', function() { var categoryId = $(this).val(); var tagsKeys = $.keys(multiLevelProducts[categoryId]); var options = []; $.each(tagsKeys, function(key, value) { options.push(tagsOptions[value]); }); $('#tag').empty().append(options); }); }
我也是新手,代码写得比较乱,希望你能看懂。
@Martin91 你可真有心,教导的这么仔细,让我收益匪浅。谢谢你
#4 楼 @yeyong14 呃,我就是当做一个习题做了一遍,js 部分的代码只是其中一部分,其他的处理是一样的方法,留给你自己做吧