I am trying to create a form so a user can save a setting which has their default teams (multiple) and their professions (single). I can do this using simple_form and the lines of code below, but I am trying to use autocomplete as the dropdown lists do not work well with my design.
<%= f.association :profession %><%= f.association :team, input_html: { multiple: true } %>
I am loading the JSON from a collection into an attribute data-autocomplete-source within my inputs, a short bit of jquery then cycles through each of these and then initialises the materialize .autocomplete, I also need to do this with .chips for many associations.
The UI element is working as I would like, but I cannot work out how to save a new record. I have two problems:
Unpermitted parameters: :team_name, :profession_name- I've been trying to adapt this tutorial and believed that Step 11 would effectively translate this within the model, but am clearly not understanding something..."setting"=>{"team_name"=>"", "profession_name"=>"Consultant Doctor"}- theteam_namevalues (i.e. thechips) are not being recognised when attempting to save the record. I've got some nasty jquery that transfers theidfrom thedivto the generatedinputwhich I was hoping would work...
I've also checked many previous questions on Stack Overflow (some of which seem to be similar to this question, generally using jqueryui) but cannot work out how to adapt the answers.
How can I use the names from a model in a materialize chip and autocomplete input and save the selections by their associated id into a record?
Any help or guidance would be much appreciated.
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
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
views/settings/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 %>
$("*[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,
});
}
});
.prefix~.chips {
margin-top: 0px;
}
<!-- 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>
Gems and versions
- ruby '2.5.0'
- gem 'rails', '~> 5.2.1'
- gem 'materialize-sass'
- gem 'material_icons'
- gem 'materialize-form'
- gem 'simple_form', '>= 4.0.1'
- gem 'client_side_validations'
- gem 'client_side_validations-simple_form'
from Using Materialize `chip` and `autocomplete` in Ruby on Rails Form with Associated Models
No comments:
Post a Comment