【问题标题】:How to get optgroup labels ID如何获取 optgroup 标签 ID
【发布时间】:2016-02-04 17:22:28
【问题描述】:

我正在尝试制作动态表单。我的类别有很多主菜并且有很多方面。当您选择主菜时,我试图根据主菜类别填充侧面。

我将进行 ajax 调用以填充此内容,但我需要类别的 ID 才能执行此操作。

我曾考虑将类别的 ID 作为类别的 ID/Class 或什至附加到每个选项,但我不知道该怎么做。

这是我的 grouped_collection 选择:

 <%= f.grouped_collection_select(:food_item, restaurant.categories, :entrees, :name, :id, :name) %>

【问题讨论】:

    标签: jquery ruby-on-rails forms ruby-on-rails-4


    【解决方案1】:

    将数据附加到 DOM

    HTML5 引入了“数据”属性——可用于将数据附加到页面上的元素:

    $('.foo').click(function(){alert($(this).data('id'))})
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <button class="foo" data-id="1" >Test</button>

    通过 grouped_collection_select,您可以使用 html_options 参数将数据附加到元素。

    获取选项

    有几种方法可以解决这个问题:

    js.erb

    将 Rails 用作“懒人”SPA。这意味着您将对/entrees/1/sides.js 之类的内容发出 AJAX 请求。

    class SidesController
    
      def index
         @entree = Entree.join(:sides).find(params[:entree_id])
         @sides = @entree.sides
    
         respond_to do |f|
           f.html 
           f.js
         end
      end
    end
    

    这将呈现一个如下所示的模板:

    // app/views/sides.js.erb
    jQuery("#some_element").html('<%=j f.grouped_collection_select(:food_item, restaurant.categories, :entrees, :name, :id, :name) %>');
    

    然而,这些 ruby​​、javascript 和 HTML 的混杂乱七八糟的东西,对我们在过去 10 年中所学到的关于构建应用程序的所有知识都是一团糟。

    很难调试正在发生的事情 - 更糟糕的是,它无法使用 javascript 测试工具进行单元测试。您必须依赖硒或水豚,这非常缓慢。

    客户端模板

    在这种情况下,您会向服务器请求 JSON 并在客户端中对其进行转换:

    假设/entrees/1/sides.json 返回一个对象数组:

    [
      { id: 1, name: 'Mashed Potatoe' },
      { id: 22, name: 'Pickled Herring' },
      { id: 51, name: 'Grilled Veggies' }
    ]
    

    您可以将其处理成一个选项元素列表,如下所示:

    var promise = $.getJSON('/entrees/1/sides.json');
    promise.pipe(function(data){
      return $.map(data, function(item){
         return $("<option>"+ item["name"] +"</option>").val(item[:id]);
      });
    }).done(function(opts){
      $('#some_element').append(opts);
    });
    

    对于更复杂的示例,您将需要使用 JS 模板系统。

    创建自定义分组选择

    <%= content_tag :select, name: "meal[food_item]" id="meal_food_item"> 
      <%= restaurant.categories.each do |c| %>
        <% uri = category_sides_path(category_id: c, format: :json) %>
        <%= content_tag(:optgroup, label: c.name, "data-uri" => uri) do %>
          <%= options_from_collection_for_select(c.entrees, 'id', 'name') %>
        <% end %>
      <% end %>
    <% end %>
    

    并不是说uri 会出现在您可以获取侧面的任何地方。

    $(".new_meal #meal_food_item").on('change', function() {
      var $selected, promise, data_uri;
      $selected = $(this).find(:selected).parents('optgroup');
      promise = $.getJSON($selected.data('uri'));
      promise.done(function(data){
        // update the sides select
      });
    });
    

    【讨论】:

    • 它已设置为您将转到 /categories/1/sides.json 和 /categories/1/entrees.json。边与类别相关联,而不是与主菜相关联。这是一个简单的示例jsfiddle.net/ky0pkavd/3(这有效,但仅在第一次更改时有效:(不确定如何使其在第二次更改时起作用,这就是我尝试使用 ajax 方法的原因)
    • 刚刚看到你的更新@max。 html_options 不起作用,因为它适用于整个集合而不是每个特定选项。
    • 我会创建一个部分输出选项,以防grouped_collection_select 没有足够的灵活性。你的小提琴的主要问题是它破坏了第二次调用中需要的“数据”。我的意思是第一次更改选项时清除“#meal_sides”,第二次更改时它就不存在了。
    • 您可以通过从 DOM 中克隆和分离 #meal_sides 中的元素并将它们存储在 .change 回调之外的 var 中来解决此问题。
    • 你愿意告诉我怎么做吗?我昨天试过了,失败得很惨@max
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    相关资源
    最近更新 更多