【问题标题】:Multiple values for collection_selectcollection_select 的多个值
【发布时间】:2012-12-31 04:14:50
【问题描述】:

我正在尝试在我的表单中包含以下 HTML 代码:

 <select name="user[language_ids][]">
    <option value="">Please select</option>
    <option value="1" selected="selected">English</option>
    <option value="2">Spanish</option>
  </select>

  <select name="user[language_ids][]">
    <option value="">Please select</option>
    <option value="1" selected="selected">English</option>
    <option value="2">Spanish</option>
  </select>

允许用户在注册时选择两种语言。

我已经试过了:

<%= f.label :languages %>
<%= f.collection_select(:language_ids, Language.all, :id, :name) %>
<%= f.collection_select(:language_ids, Language.all, :id, :name) %>

还有这个:

<%= f.label :languages %>
<%= f.collection_select(:language_ids[], Language.all, :id, :name) %>
<%= f.collection_select(:language_ids[], Language.all, :id, :name) %>

在查看答案后,我尝试了这个:

<%= collection_select(:user, :language_ids, Language.all, :id, :name, {}, {:name => 'user[language_ids][]' }) %>
    <%= collection_select(:user, :language_ids, Language.all, :id, :name, {}, {:name => 'user[language_ids][]' }) %>

但这里的问题是两个选择具有相同的 ID,而且它们与表单构建器 f 没有关联

有什么好的方法吗?

【问题讨论】:

  • 您是否在 show.html.erb 中看到语言的 ID 而不是它们的名称?
  • 选择字段与模型有何关系?

标签: ruby-on-rails forms


【解决方案1】:

试试,

<%= f.collection_select(:language_ids, Language.all, :id, :name,{}, {:multiple => true}) %>

【讨论】:

  • 我不想要多个,我想要几个选择...谢谢
  • 不是问题的正确答案,而是我的正确答案,非常感谢!
【解决方案2】:

您可以使用以下方法创建字段集合 fields_for.
这两个选择将具有相同的 id 但 collection_select 接受一个包含 html 选项的可选哈希,您可以在其中设置自定义 id。

<%= f.fields_for :language_ids do |language| %>
  <%= language.collection_select(nil, Language.all, :id, :name,
        {include_blank: "Please select", selected: 1},
        {id: :user_language_id_1}) %>
  <%= language.collection_select(nil, Language.all, :id, :name,
        {include_blank: "Please select", selected: 1},
        {id: :user_language_id_2}) %>
<% end %>

生成以下输出:

<select id="user_language_id_1" name="user[language_ids][]">
  <option value="">Please select</option>
  <option value="1" selected="selected">English</option>
  <option value="2">Spanish</option>
</select>

<select id="user_language_id_2" name="user[language_ids][]">
  <option value="">Please select</option>
  <option value="1" selected="selected">English</option>
  <option value="2">Spanish</option>
</select>

【讨论】:

    【解决方案3】:

    由于您在选择的名称属性中写了“user[language_ids][]”,我不得不假设您需要一个多选框。你应该这样做:

    f.collection_select (:language_ids, Language.all, :id, :name, 
    {:prompt => true}, {:multiple => true})
    

    当然,这不是一个记录良好的功能。

    编辑:进一步查看您的示例和一些答案,我想指出一些事情:

    • 您的示例将提示“请选择”作为选择框的第一个选项,但是您希望在两个示例中都选择“英语”。如果您希望预先选择一个选项,它以及选择框的第一个选项,那为什么会有提示选项呢?用它来强制用户选择一些东西。

    • 您在一个答案中写道,您想要多选而不是多选,这是您不想要 :multiple => true 解决方案的原因。我仍然建议您使用它,但也许您确实有必要的用例。因此,我建议您直接使用 select_tag 助手(我认为您不会使用表单标签助手来实现):

      select_tag "user[language_ids][]", 
      options_from_collection_for_select(Language.all, "id", "name"), 
      :prompt => true, :id => "user_language_ids"
      

      这里的关键是,多个选择必须有不同的 id,你必须明确地传递,所以它会在你手中。

    【讨论】:

      【解决方案4】:

      你应该可以做这样的事情:

      <%= f.label :languages %>
      <%= f.collection_select(:language_ids, Language.all, :id, :name, {}, {id => "language_1", :name => "user[language_ids][]"}) %>
      <%= f.collection_select(:language_ids, Language.all, :id, :name, {}, {id => "language_2", :name => "user[language_ids][]"}) %>
      

      【讨论】:

        【解决方案5】:

        基本上发送 2 个(或更多)具有相同属性的字段是行不通的,因为 params 将被转换为哈希:{language_ids: [1], language_ids: [2]} 并且由于您拥有相同的密钥,因此最后一个将覆盖前一个(s) .

        {a: 1, a: 2}[:a] #=> 2
        

        要避免这个问题,您需要创建不同的属性,然后将它们连接成一个。为此,您需要模型中的外观属性:

        class Language
          attr_writer :language_one_id, :language_two_id
        
          before_save :gather_languages
        
          def gather_languages
            self.language_ids= [language_one_id, language_two_id]
          end
        
          # for the form to display chosen lang (idem with two)
          def language_id
            language_ids.first
          end
        end
        
        # view/_form
        =f.select :language_one_id, Language.all.map {|l| [l.name, l.id]}
        =f.select :language_two_id, Language.all.map {|l| [l.name, l.id]}
        

        但坦率地说,我认为你在这里违反惯例会让你的生活变得更加艰难(我会使用复选框)。

        【讨论】:

          【解决方案6】:

          您可以在表格中添加“second_language”列,然后使其具有与第一个语言列相同的内容。

          【讨论】:

            【解决方案7】:

            你可以像这样使用 fields_for:

            <%= form_for @user do |f| %>
             ...
            <h2>Languages</h2>
            <%= fields_for :languages do |lang_form| %>
              <%= lang_form.collection_select :language_id, Language.all, :id, :name %>
            <% end %>
            ..
            <% end %>
            

            在您的控制器上,在您的新方法或编辑方法中,您可以执行此操作以接受 2 种语言

            2.times { @user.languages.build }
            

            【讨论】:

              【解决方案8】:

              首先你必须编辑你的用户模型:

              用户.rb

              has_many :languages
              accepts_nested_attributes_for :languages
              

              下一步生成模型:

              $> rails g model language user_id:integer name
              

              语言.rb

              belongs_to  :user
              

              users_controller.rb(可能在“新”操作中)

              2.times do
                language = @user.language.build
              end
              

              _form.html.erb

              <%= form_for @user do |f| %>
                <%= f.fields_for :languages do |lang| %>
                  <%= lang.label :name, "Name" %><br />
                  <%= lang.select :name, Language.all.collect {|l| [l.name, l.id]}, prompt: 'Please select' %><br /> 
                <%= end %>     
                <p><%= f.submit "Submit" %></p>
              <% end %>
              

              【讨论】:

                【解决方案9】:

                试试这个:

                <%=select_tag "language_ids[]" options_for_select([['Please select','']]+Language.all.map{|ln|[ln.name,ln.id]})%>
                

                【讨论】:

                • 这只是进行collection_select的另一种方式。不能解决作者的问题
                【解决方案10】:

                使用宝石,宝石“茧”

                以模型的形式添加你想要的字段

                  <div class="form-group">
                    <%= f.fields_for :photoproducts do |forms_fields| %>
                      <% render partial: "shared/photoproducts_fields", locals: {f: forms_fields} %>
                    <% end %>
                    <%= link_to_add_association('+ Foto', f, :photoproducts, type: "button", class: "btn btn-primary btn-sm") %>
                  </div>
                

                (在本例中,我有一个产品模板,我正在向其中添加照片)

                然后在项目根目录的共享文件夹中创建一个部分。

                -

                项目/共享/_fotoproduto_fields.html.erb

                <div class="nested-fields">
                  <%= link_to_remove_association('remove photo', f, type: "button", class: "btn btn-danger btn-sm") %>
                  <div class="photoproducts">
                    <div class="form-group">
                      <label class="control-label"><%= f.label :name %></label>
                      <%= f.text_field :name, class: "form-control", type: "text" %>
                    </div>
                    <div class="form-group">
                      <label class="control-label"> photo</label>
                      <%= f.file_field :files, class: "form-control" %><br/><br/>
                    </div>
                  </div>
                </div>
                

                这样你会得到一个更动态的表单

                记得将参数放入嵌套属性的控制器中,并放入 create 方法,即模型的构建。

                例如:@products.photoproducts.build

                【讨论】:

                  猜你喜欢
                  • 2015-12-18
                  • 2015-08-12
                  • 2018-08-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-04
                  • 2014-06-25
                  相关资源
                  最近更新 更多