我过去常常使用collection_select
与<select>
建立<options>
。
<%= f.label :members, class: "mdl-textfield__label" %>
<%= f.collection_select :user_ids, User.where.not(id: current_user).collect, :id, :email, {include_hidden: false}, {:class => "mdl-textfield__input", :multiple => true} %>
后端的帖子很好,看起来像这样:
{"utf8"=>"✓",
"authenticity_token"=>"redacted",
"groupchat"=>{"topic" =>"5dd",
"user_ids"=>["5","6","7","8"]},
"commit"=>"Done"}
我想在控制器中使用它的方式:
def groupchat_params
params.require(:groupchat).permit(:topic, {:user_ids => []})
end
问题:我正在尝试使用无序列表ul
和li
重新创建此功能,因为这是跨平台列表选择器的共识。这就是我所拥有的:
<ul id="special-select">
<%= f.hidden_field :user_ids, { multiple: true, value: [] } %>
<% User.where.not(id:current_user).each do |user| %>
<li class="groupmember-select" id=<%= user.id %> value=<%= user.id %>>
<%= user.name %>
</li>
<% end %>
</ul>
我使用JavaScript变量来存储我选择的数组。所有这些都有效,据我所知,这不是问题,我不想把这个问题弄得乱七八糟。我认为是这种情况,因为以下是我的上述.html.erb
的脚本:
var user_ids = [];
$("#special-select li").click(function(){
var index = user_ids.indexOf($(this).attr("value"));
if (index > -1) {
user_ids.splice(index, 1);
}
else {
user_ids.push($(this).attr("value"));
}
$("#groupchat_user_ids").val(user_ids);
$(this).toggleClass("selected");
});
当我选择一些项目并在浏览器控制台中查看时,它看起来就像我需要的那样:
> user_ids
["2", "6", "3"]
但是我注意到,当我右键单击浏览器中的对象并粘贴它时,我得到以下内容:
> user_ids
[0: "2", 1: "6", 2: "3", length: 3]
当我使用提交按钮发布上述表单时,我得到以下内容(所有项目都在一个字符串中,以逗号分隔):
{"utf8"=>"✓",
"authenticity_token"=>"redacted",
"groupchat"=>{"topic" =>"5dd",
"user_ids"=>["5,6,7,8"]},
"commit"=>"Done"}
我已经尝试JSON.stringify
(输出未更改,看起来与上面相同)和JSON.parse
(几乎像我需要的那样,但是在后端的POST中可以看到转义的引号,无论如何没有工作。
之前我遇到过一个非常类似的问题,但是在我:user_ids
默认为数组之前。
任何见解都会很棒!
答案 0 :(得分:1)
您只能通过一个隐藏字段传递数组。您需要做的是添加多个具有相同名称的隐藏字段。生成的HTML应如下所示:
<input value="1" multiple="multiple" type="hidden" name="groupchat[user_ids][]">
<input value="2" multiple="multiple" type="hidden" name="groupchat[user_ids][]">
<input value="3" multiple="multiple" type="hidden" name="groupchat[user_ids][]">
因此,您不需要将val
更改为数组,而是需要创建多个隐藏标记,并通过javascript跟踪它们。
您可以在正在使用的data-hidden-field-tag
元素上使用li
属性,并将其存储以代替user_ids
数组。在表单中有一个id hidden-fields
div或任何你想要的div,并且每次有变化时都用隐藏字段更新div。
编辑:根据您的应用程序添加代码。
HTML部分。
<div id="hidden-fields" style="display: none;"></div>
<ul id="special-select">
<% User.where.not(id: current_user.id).each do |user| %>
<li class="groupmember-select" id=<%= user.id %> value=<%= user.id %> data-hidden-field-tag="<%= html_escape_once f.hidden_field(:user_ids, { multiple: true, value: user.id }) %>" >
<%= user.identity %>
</li>
<% end %>
</ul>
Javascript部分:
var selectedUsers = [];
$("#special-select li").click(function(){
var index = selectedUsers.indexOf($(this).attr("data-hidden-field-tag"));
if (index > -1) {
selectedUsers.splice(index, 1);
}
else {
selectedUsers.push($(this).attr("data-hidden-field-tag"));
}
$("#hidden-fields").html(selectedUsers);
$(this).toggleClass("selected");
});