I had a form for announcements. I need to hide some divs when user choose something. For example, when user choose 'Buy', i need to hide div with :services. User must to see only divs for 'Buy'. If user choose "chat", we don't need "city", "images", and others, only create. This is my form:
= form_with(model: @room, local: true, html: {multipart: true}) do |f|
- if @room && @room.errors.any?
#error_explanation
%h2= "#{pluralize(@room.errors.count, "error")} prohibited this room from being saved:"
%ul
- @room.errors.full_messages.each do |message|
%li= message
.form-group.mb-3
= f.select :cat_route,[ "channel", "chat", "bot", "service"], class: 'form-
control'
.form-group.mb-3
= f.select :services,["option1", "option2", "option3"], class: 'form-control'
.form-group.mb-3
= f.select :route,["Buy", "Sell"], class: 'form-control'
.form-group.mb-3
= f.select :city,["City1", "City2", "City3"], class: 'form-control'
.form-group.mb-3
= f.text_field :name, placeholder: "name", class: 'form-control'
.form-group.mb-3
= f.text_field :link, placeholder: "link", class: 'form-control'
.form-group.mb-3
= f.select :category,["SMM", "IT", "Gif Video"], class: 'form-control'
.form-group.mb-3
= f.text_field :content, class: 'form-control'
.form-group.mb-3
= f.text_field :price, class: 'form-control'
.form-group.mb-3
= f.label 'Image'
= f.file_field :image, class: 'form-control'
.form-group.mb-3
= f.check_box :free, id: 'free', class: 'form-check-input'
%b= f.label :option, 'Free', class: 'form-check-label', for: 'free'
.form-group.mb-3
= f.check_box :hot, id: 'hot', class: 'form-check-input'
= f.label 'hot', class: 'form-check-label small', for: 'hot'
%br
.actions
= f.submit 'Create', class: 'btn btn-outline-primary btn-block'
CodePudding user response:
It's not very clear from your description what exactly you want to hide/show depending on selected options but you definitely need JS
here to do this:
And you didn't mention what Rails version
you use. Depending on this JS
can be placed in Stimulus controller
on in js
file in assets pipeline
But I can provide you a raw snipper of js
in your view
file that does what you described in the question, rest you can implement according to the js template
= form_with(model: @room, local: true, html: {multipart: true}) do |f|
- if @room && @room.errors.any?
#error_explanation
h2= "#{pluralize(@room.errors.count, "error")} prohibited this room from being saved:"
ul
- @room.errors.full_messages.each do |message|
li= message
.form-group.mb-3
= f.select :cat_route,[ "channel", "chat", "bot", "service"], class: 'form-control'
#other_blocks
.form-group.mb-3
= f.select :services,["option1", "option2", "option3"], class: 'form-control'
.form-group.mb-3
= f.select :route, ["Buy", "Sell"], class: 'form-control', include_blank: true
.form-group.mb-3
= f.select :city,["City1", "City2", "City3"], class: 'form-control'
.form-group.mb-3
= f.text_field :name, placeholder: "name", class: 'form-control'
.form-group.mb-3
= f.text_field :link, placeholder: "link", class: 'form-control'
.form-group.mb-3
= f.select :category,["SMM", "IT", "Gif Video"], class: 'form-control'
.form-group.mb-3
= f.text_field :content, class: 'form-control'
.form-group.mb-3
= f.text_field :price, class: 'form-control'
.form-group.mb-3
= f.label 'Image'
= f.file_field :image, class: 'form-control'
.form-group.mb-3
= f.check_box :free, id: 'free', class: 'form-check-input'
b= f.label :option, 'Free', class: 'form-check-label', for: 'free'
.form-group.mb-3
= f.check_box :hot, id: 'hot', class: 'form-check-input'
= f.label 'hot', class: 'form-check-label small', for: 'hot'
br
.actions
= f.submit 'Create', class: 'btn btn-outline-primary btn-block'
javascript:
const roomRouteSelect = document.querySelector('#room_route')
const roomCatRouteSelect = document.querySelector('#room_cat_route')
const roomServicesSelect = document.querySelector('#room_services')
const otherBlocks = document.querySelector('#other_blocks')
roomRouteSelect.addEventListener('change', (e) => {
if (e.target.value == 'Buy') {
roomServicesSelect.classList.add('d-none')
} else {
roomServicesSelect.classList.remove('d-none')
}
})
roomCatRouteSelect.addEventListener('change', (e) => {
if (e.target.value == 'chat') {
otherBlocks.classList.add('d-none')
} else {
otherBlocks.classList.remove('d-none')
}
})
Note: I wrapped some inputs in #other_blocks
div, don't forget to add it to your form. Also I added include_blank: true
to = f.select :route, ["Buy", "Sell"], class: 'form-control'
so that you can see changes when you select this option
CodePudding user response:
I do not know Ruby. Assuming f.select :route
means
<select id="route"
then I suggest the following - I guessed the HTML:
const form = document.querySelector("form");
const notChat = [...document.querySelectorAll(".form-control, .form-check-input, label")].slice(1); // all form-control except the first
form.addEventListener("change", e => {
const tgt = e.target;
if (tgt.id === "route") {
document.getElementById("services").hidden = tgt.value === "Buy";
} else if (tgt.id === "cat_route") {
const hide = tgt.value === "chat"; console.log(hide)
notChat.forEach(formControl => formControl.hidden = hide);
}
})
<form>
<div >
<select name="cat_route" id="cat_route" >
<option>channel</option>
<option>chat</option>
<option>bot</option>
<option>service</option>
</select>
</div>
<div >
<select name="services" id="services" >
<option>option1</option>
<option>option2</option>
<option>option3</option>
</select>
</div>
<div >
<select name="route" id="route" >
<option>Buy</option>
<option>Sell</option>
</select>
</div>
<div >
<select name="city" id="city" >
<option>City1</option>
<option>City2</option>
<option>City3</option>
</select>
</div>
<div >
<input type="text" name="name" id="name" placeholder="name" >
</div>
<div >
<input type="text" name="link" id="link" placeholder="link" >
</div>
<div >
<select name="category" id="category" >
<option>SMM</option>
<option>IT</option>
<option>Video</option>
</select>
</div>
<div >
<input type="text" id="content" >
</div>
<div >
<input type="text" id="price" >
</div>
<div >
<label>Image <input type="file" id="image" ></label>
</div>
<div >
<label id="option" for="free">Free</label> <input type="checkbox" id="free" >
</div>
<div >
<label id="option" for="hot">hot</label> <input type="checkbox" id="hot" >
</div>
<input type="submit" value="Create" />
</form>