如果我将一个数组保存到数据库中,它会被正确保存,但是当我查看表单时,它会在所有数组输入字段的数组中放入连接值。
E.g。在下面的表格中,我有2个输入字段,因此您可以在数组列中为Pet存储2个昵称。我把" a"在字段1和" b"在字段2中按保存。我在Rails控制台中检查并正确存储:nicknames: ["a", "b"]
。但是当我打开表单时,两个输入字段都包含" a b"。所以价值观以某种方式连接起来。我做错了什么?
重现:
rails g scaffold Pets
然后在新的迁移中:
class CreatePets < ActiveRecord::Migration
def change
create_table :pets do |t|
t.string :nicknames, array: true
t.timestamps null: false
end
end
end
在控制器中:
def pet_params
params[:pet].permit(nicknames: [])
end
表格形式:
<%= simple_form_for(@pet) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.text_field :nicknames, name: 'pet[nicknames][]' %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]' %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
创建一个带有昵称的新宠物&#34; a&#34;和&#34; b&#34;。去编辑宠物,输入现在包含&#34; a b&#34;和&#34; b&#34;,但它存储为&#39;昵称:[&#34; a&#34;,&#34; b&#34;]&#39;根据Rails控制台在数据库中。
答案 0 :(得分:2)
检查是否@pet.persisted
如果是,请循环显示值并显示。
如果不是,请像往常一样做新事。
<div class="form-inputs">
<% if @pet.persisted? && (@pet.nicknames.length > 0) %>
<% @pet.nicknames.each do |nickname| %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]', value: nickname %>
<% end %>
<% else %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]' %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]' %>
<% end %>
</div>
答案 1 :(得分:1)
简单表单不知道如何执行此操作,因此您可以编写自己的自定义输入(在gem README和上面的@ Thanh&#39链接中描述),或者您可以告诉它要使用的值:
<div class="form-inputs">
<%= f.text_field :nicknames, name: 'pet[nicknames][]', value: @pet.nicknames.try(:first) %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]', value: @pet.nicknames.try(:second) %>
</div>
答案 2 :(得分:1)
我认为昵称是由用户输入的,而不是从列表中选择的。因此,您是否考虑过如何添加和删除昵称?只有两个不是太繁重,但将它们存储在array
意味着可能在某些时候更多?
此处的一个选项是保持表单简单,但使用Selectize.js等JavaScript库来添加功能(直接集成,或通过selectize-rails)。这允许用户使用昵称作为列表,并节省您编写额外JS以添加或删除条目的工作。
然后您的表单简化为:
<%= simple_form_for(@pet) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :nicknames %>
<%# untested - you might need to append `input_html: { value: @pet.nicknames.join(',') }` %>
</div>
...
你可以像这样初始化输入:
$('.pet_nicknames').selectize({
delimiter: ',',
placeholder: 'Type in nickname(s)',
create: function(input) {
return {
value: input,
text: input
}
}
});
您可以查看usage options for Selectize here,例如如果您需要限制用户可以输入的最大昵称数。
答案 3 :(得分:1)
每个字段都有a b
,因为您有相同的字段::nicknames
你应该做的是为每一个生成多个字段,几乎就像保罗在这里说的那样,但方法略有不同。
在您看来:
<div class="form-inputs">
<% @pet.nicknames.each do |nickname| %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]', value: nickname %>
<% end %>
<%= f.text_field :nicknames, name: 'pet[nicknames][]' %>
<%= f.hidden_field :nicknames, name: 'pet[nicknames][]', disabled: true, class: 'js-nickname-input-template' %>
</div>
即使在new
记录中,也会为昵称呈现一个字段,其中还没有昵称。如果你edit
,每个昵称都会有一个字段,而一个昵称则为空。
还有一个隐藏的禁用字段,用于呈现给您的下一个任务。
要使其完全正常运行,您应该添加javascript功能,以添加或销毁昵称字段。
在您的javascript资源中:
$('#some-button-for-new').click(function(e){
$templ = $('.js-nickname-input-template');
$el = $templ.clone();
$el.removeClass('.js-nickname-input-template');
$el.removeAttr('disabled');
$el.attr('type', 'text');
$templ.before($el);
});
$('.some-button-for-destroy').click(function(e){
$el = $($(e.target).data('identifier'));
$el.remove();
});
因此,第一个处理程序为昵称添加新字段,第二个处理程序删除元素。注意:这不是copypaste准备好的,特别是去除。您可能希望处理应删除的元素(可能包含一些li
或div
包含字段和删除按钮本身。)
tl; dr:想法是为每个现有的数组元素服务器端创建字段,加上一个空的加模板。 您可以使用模板使用javascript添加和删除字段。