Oli*_*ure 8 javascript ruby jquery ruby-on-rails materialize
我正在尝试创建一个表单,以便用户可以保存setting具有默认teams(多个)和他们professions(单个)的表单.我可以使用simple_form以下代码行完成此操作,但我尝试使用自动完成功能,因为下拉列表与我的设计不兼容.
<%= f.association :profession %><%= f.association :team, input_html: { multiple: true } %>我正在将一个集合中的JSON加载到data-autocomplete-source我的一个属性中inputs,jquery然后稍微循环一下这些属性,然后初始化实现.autocomplete,我还需要.chips为许多关联做这个.
UI元素正在按照我的意愿工作,但我无法弄清楚如何保存新记录.我有两个问题:
Unpermitted parameters: :team_name, :profession_name- 我一直在努力调整本教程并相信Step 11会在模型中有效地转换它,但显然不理解某些东西......"setting"=>{"team_name"=>"", "profession_name"=>"Consultant Doctor"}- 尝试保存记录时未识别team_name值(即chips).我有一些讨厌的jQuery转移了对id从div所生成的input,我希望会工作...我还检查过很多关于Stack Overflow的问题(其中一些似乎与这个问题类似,通常使用jqueryui),但无法弄清楚如何调整答案.
如何在实体化chip和autocomplete输入中使用模型中的名称并将它们的关联保存id到记录中?
任何帮助或指导将不胜感激.
setting.rb
class Setting < ApplicationRecord
has_and_belongs_to_many :team, optional: true
belongs_to :user
belongs_to :profession
def team_name
team.try(:name)
end
def team_name=(name)
self.team = Team.find_by(name: name) if name.present?
end
def profession_name
profession.try(:name)
end
def profession_name=(name)
self.profession = Profession.find_by(name: name) if name.present?
end
end
Run Code Online (Sandbox Code Playgroud)
settings_controller.rb
def new
@user = current_user
@professions = Profession.all
@teams = Team.all
@setting = Setting.new
@teams_json = @teams.map(&:name)
@professions_json = @professions.map(&:name)
render layout: "modal"
end
def create
@user = current_user
@setting = @user.settings.create(setting_params)
if @setting.save
redirect_to action: "index"
else
flash[:success] = "Failed to save settings"
render "new"
end
end
private
def setting_params
params.require(:setting).permit(:user_id, :contact, :view, :taketime, :sortname, :sortlocation, :sortteam, :sortnameorder, :sortlocationorder, :sortteamorder, :location_id, :profession_id, :department_id, team_ids: [])
end
Run Code Online (Sandbox Code Playgroud)
查看/设置/ new.html.erb
<%= simple_form_for @setting do |f| %>
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field autocomplete_dynamic col s12">
<i class="material-icons prefix">group</i>
<div data-autocomplete-source='<%= @teams_json %>' class="string optional chips" type="text" name="setting[team_name]" id="setting_team_name"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field autocomplete_dynamic col s12">
<i class="material-icons prefix">group</i>
<%= f.input :profession_name, wrapper: false, label: false, as: :search, input_html: {:data => {autocomplete_source: @professions_json} } %>
<label for="autocomplete-input">Select your role</label>
</div>
</div>
</div>
</div>
<%= f.submit %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
$("*[data-autocomplete-source]").each(function() {
var items = [];
var dataJSON = JSON.parse($(this).attr("data-autocomplete-source"));
var i;
for (i = 0; i < dataJSON.length; ++i) {
items[dataJSON[i]] = null;
}
if ($(this).hasClass("chips")) {
$(this).chips({
placeholder: $(this).attr("placeholder"),
autocompleteOptions: {
data: items,
limit: Infinity,
minLength: 1
}
});
// Ugly jquery to give the generated input the correct id and name
idStore = $(this).attr("id");
$(this).attr("id", idStore + "_wrapper");
nameStore = $(this).attr("name");
$(this).attr("name", nameStore + "_wrapper");
$(this).find("input").each(function() {
$(this).attr("id", idStore);
$(this).attr("name", nameStore);
});
} else {
$(this).autocomplete({
data: items,
});
}
});Run Code Online (Sandbox Code Playgroud)
.prefix~.chips {
margin-top: 0px;
}Run Code Online (Sandbox Code Playgroud)
<!-- jquery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Materialize CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!-- Materialize JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- Material Icon Webfont -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field autocomplete_dynamic col s12">
<i class="material-icons prefix">group</i>
<div data-autocomplete-source='["Miss T","Mr C","Mr D","Medicine Take","Surgery Take"]' class="string optional chips" type="text" name="setting[team_name]" id="setting_team_name"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field autocomplete_dynamic col s12">
<i class="material-icons prefix">group</i>
<input class="string optional input-field" data-autocomplete-source='["Consultant Doctor","Ward Clerk","Nurse","Foundation Doctor (FY1)","Foundation Doctor (FY2)","Core Trainee Doctor (CT2)","Core Trainee Doctor (CT1)"]' type="text" name="setting[profession_name]"
id="setting_profession_name">
<label for="autocomplete-input">Select your role</label>
</div>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
宝石和版本
\n\n\n几乎可以肯定这不是最好的方法,但它确实有效。请提供建议,我会更新此内容,或者如果有人添加更好的答案,我会很乐意将其标记为正确。该解决方案不需要太多控制器/模型更改,并且很大程度上是通过(相对)较短的 jquery/JS 完成的,因此可以在项目中轻松重复。
\n
我已经设法让自动完成和芯片与 Ruby on Rails 一起使用,并尽可能利用 simple_form 表单助手。
\n\n实际上,我将 JSON 存储到每种情况的自定义属性中,然后在加载视图时使用一些 jquery/javascript 对其进行解析,然后再使用它来初始化autocomplete或chips。
自动完成值在控制器内从名称转换为 ID。
\n\n客户端使用一些 JS 来识别芯片值,并使用正确name和正确的方式创建输入id形式,以自动将值作为数组保存到哈希中。
完整的解释和代码如下。
\n\n谢谢你汤姆的有用评论和意见。
\n\nautocomplete要求您在变量_name下创建输入,然后在模型中添加其他函数以将名称转换为 id 进行保存。有效地遵循本教程。
\n\n<%= f.input :profession_name, input_html: { data: { autocomplete: @professions_json } } %>\nRun Code Online (Sandbox Code Playgroud)\n\n正如您在上面看到的,与添加典型的 simple_form 关联的唯一真正区别如下:
\n\nf.input而不是f.association- 确保呈现文本框而不是下拉列表:model_name而不是:model- 确保控制器识别出这是一个需要转换为对象的名称input_html: { data: { autocomplete: @model_json } }- 这会添加一个包含所有 JSON 数据的自定义属性,这是由您需要确保模型的名称是唯一的。
\n\nchips这有点复杂,需要额外的 JavaScript 函数。该代码将回调附加到添加或删除芯片的事件,然后循环遍历每个芯片并添加隐藏的input. 每个输入都有一个与 simple_form 期望的名称属性相匹配的名称属性,因此在提交到控制器之前它会被正确添加到哈希参数中。我无法让它翻译数组中的多个名称,所以只是让它重新读取原始 JSON 中的 id 并将其添加为输入的值。
<div id="team_ids" placeholder="Add a team" name="setting[team_ids]" class="chips" data-autocomplete="<%= @teams_json %>"></div>\nRun Code Online (Sandbox Code Playgroud)\n\n从上面你可以看到与 simple_form 约定有以下偏差:
\n\n<div>而不是 a,<% f.input %>因为需要在 div 上调用 Materialise 芯片placeholder="..."一旦芯片初始化,此文本将用作占位符,可以留空/不包含name="setting[team_ids]"帮助 simple_form 了解这适用于哪个模型class="chips"确保我们的 JavaScript 稍后知道要chips在此元素上进行初始化data-autocomplete="<%= @teams_json %>"将JSON数据保存为div的属性以供稍后解析\n\n\n目前,代码重新解析原始 JSON 属性,可以引用在芯片初始化时创建的 JSON 数据,这可能更好,但我无法让它工作。
\n\n自定义输入元素- 比我更有经验的人可能能够尝试这个并为 simple_form 创建自定义元素......不幸的是,这超出了我的范围。
\n
设置_控制器.rb
\n\n<%= f.input :profession_name, input_html: { data: { autocomplete: @professions_json } } %>\nRun Code Online (Sandbox Code Playgroud)\n\n设置.rb
\n\n <div id="team_ids" placeholder="Add a team" name="setting[team_ids]" class="chips" data-autocomplete="<%= @teams_json %>"></div>\nRun Code Online (Sandbox Code Playgroud)\n\n_form.html.erb 注意 这是部分内容,如前面的下划线所示
\n\nclass SettingsController < ApplicationController\n\n ...\n\n def new\n\n @user = current_user\n @setting = Setting.new\n @professions = Profession.select(:name)\n @teams = Team.select(:id, :name)\n\n # Prepare JSON for autocomplete and chips\n @teams_json = @teams.to_json(:only => [:id, :name] )\n @professions_json = @professions.to_json(:only => [:name] )\n\n end\n\n\n ....\n\n private\n def setting_params\n params.require(:setting).permit( :profession_name, :user_id, :profession_id, team_ids: [])\n end\nRun Code Online (Sandbox Code Playgroud)\n\nclass Setting < ApplicationRecord\n\n has_and_belongs_to_many :teams, optional: true \n belongs_to :user\n belongs_to :profession, optional: true\n\n def profession_name\n profession.try(:name)\n end\n\n def profession_name=(name)\n self.profession = Profession.find_by(name: name) if name.present?\n end\nRun Code Online (Sandbox Code Playgroud)\r\n<%= simple_form_for @setting, validate: true, remote: true do |f| %>\n\n <%= f.input :profession_name, input_html: { data: { autocomplete: @professions_json } } %>\n\n <div id="team_ids" placeholder="Add a team" name="setting[team_ids]" class="chips" data-autocomplete="<%= @teams_json %>"></div>\n\n <%= f.submit %>\n\n<% end %>\nRun Code Online (Sandbox Code Playgroud)\r\n| 归档时间: |
|
| 查看次数: |
531 次 |
| 最近记录: |