Remove form input based on value in simple form collection - javascript

In my rails app I have a lesson model that belongs to a course. In the lesson new page, there is a collection of courses that can be selected for the lesson. Courses have several 'course_types' but the most important one for this question is the 'physical' course_type. This is the sample code
<%= f.association :course, collection: current_academy.courses.collect
{ |u| [u.title, u.id] }, prompt: t("select") %>
On the same page, you can add a video link to the lesson
<%= f.input :video, label: t(".vimeo_link_to_video") %>
I want to be able to remove the video link if the course_type is 'physical'.
In my js, I have
document.addEventListener('DOMContentLoaded',function() {
document.querySelector('select[name="lesson[course_id]"]').onchange=changeEventHandler;
},false);
function changeEventHandler(event) {
if(event.target.value == "97" ) {
$(".vimeo").hide();
}
else {
$(".vimeo").show();
}
}
At the moment, I have to enter the course id, to make it work. What i want is to be able to derive the course type dynamically. So essentially i would like to do something like this in javascript
if(event.target.value == course.physical? )
How I can remove the video form input dynamically with Javascript when the value of the course is a 'physical' course_type.

Related

Rails + StimulusJS dynamically created select menu doesn't work

I'm dynamically adding fields to my form. In case of a standard text field it works fine with Rails + StimulusJS with an <template> element.
I'm using MaterializeCSS for styling and if I try to do the same thing with a select menu, it breaks and it seems the innerHTML I get back in my JS code doesn't match the code inside the template-tag. So I decided to use a div instead which I duplicate.
The view code (the relevant part):
<div data-nested-form-target="template">
<%= f.fields_for :stations, department.stations.build, child_index: "NEW_RECORD" do |station| %>
<%= render "admin/departments/stations/station_fields", f: station %>
<% end %>
This is the template I duplicte in my Stimulus controller.
This is what the first (and working) select menu looks like in HTML:
So the next step was to change the ID'S of the <ul> and the two <li> elements + the data-target element to target the right select menu.
What I ended up was this JS-Code, which is indeed adding a second select menu with the right styles, but it is not clickable and doesn't show options, despite they exist in the HTML markup and the ID's differ from the first one:
add_association(event) {
event.preventDefault()
let random_id = this.generate_random_id()
let content = this.templateTarget.cloneNode(true)
content.getElementsByTagName("ul").item(0).setAttribute("id", random_id)
content.getElementsByClassName("dropdown-trigger").item(0).setAttribute("data-target", random_id)
let list_elements = Array.from(content.getElementsByTagName("ul").item(0).querySelectorAll("li"))
list_elements.forEach((item) => {
let rnd = this.generate_random_id()
item.setAttribute("id", rnd)
})
let html = content.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
this.linksTarget.insertAdjacentHTML("beforebegin", html)
console.log(html)
let collection = this.basicTarget.getElementsByClassName("nested-fields")
let element = collection[collection.length - 1].getElementsByClassName("animate__animated")[0]
element.classList.add(this.fadeInClass)
}
Now it looks like this and I can't figure out how to make this thing working:
We're using the same stack (Rails, Stimulus.js, Materialize) with no problem. One thing you have to do after updating the select is re-initialize the Materialize select. For example, this is a general purpose nested select controller in which different sub-selects become active based on the parent select:
import { Controller } from 'stimulus';
import Materialize from 'materialize-css';
export default class extends Controller {
static targets = [
'childSelect',
]
parentSelectChanged (e) {
const selectedParentMenu = e.target.value;
this.childSelectTargets.forEach(selectElement => {
if (selectElement.dataset.parentMenuName === selectedParentMenu) {
selectElement.disabled = false;
selectElement.value = '';
} else {
selectElement.disabled = true;
}
Materialize.FormSelect.init(selectElement);
});
}
}
And here is the corresponding Haml:
.input-field.col
= select_tag :category,
options_for_select(grouped_conditions.keys.sort, selected_parent_menu_name),
include_blank: 'Select One...',
data: { action: 'nested-select#parentSelectChanged' }
.input-field.col.hide-disabled
- grouped_conditions.each do |parent_menu_name, child_conditions|
= f.select :condition_id,
options_for_select(child_conditions.sort_by(&:menu_name).map{ |tc| [tc.menu_name, tc.id] }, selected_condition_id),
{ include_blank: 'Select One...' },
disabled: selected_parent_menu_name != parent_menu_name,
data: { 'nested-select-target' => 'childSelect', 'parent-menu-name' => parent_menu_name }
= f.label :condition_id

Rails - Javascript - Add param to params before form submit

I have a form for multiple pupils, with checkboxes next to each pupil to collect their IDs. I'm trying to have two buttons that each lead to different forms, and I've tried submitted params with the button click but to no avail:
simple_form_for - multiple submit buttons with different params
Is there any way to write some JS that adds a parameter to the params before submitting the form? My form is as follows:
<%= simple_form_for :pupils, url: edit_multiple_school_group_pupils_path(school, group) do |f| %>
...
...
<%= f.button :submit, 'Change Levels', name: 'editing', value: 'levels' %>
<%= f.button :submit, 'Move to A Class', name: 'editing', value: 'classes' %>
<% end %>
Each of the buttons have their own ID in the raw HTML so I'm hoping theres a way to pluck that before the form gets submitted and add it to the params.
I'm extremely green with JS so wouldn't even know where to start. Thanks in advance.
I'm not 100% sure what is needed for the rails portion, but it sounds like you want to serialize your form.
This is fairly easily accomplished. Here is an example of what a serialize to JSON function might look like
function toJSONString( form ) {
var obj = {};
var elements = form.querySelectorAll( selectors );
for( var i = 0; i < elements.length; ++i ) {
var element = elements[i];
var name = element.name;
var value = element.value;
if( name ) {
obj[ name ] = value;
}
}
return JSON.stringify( obj );
}
The selectors can be pretty much whatever you want within your form. Inputs, textareas, buttons etc.
Hope this helps!

Display only three inputs in your dropdown using selectize.js

I am using selectize.js for a nice dropdown, however I'm trying to show only three results when its dropped down instead of the full 20 that I've got. Thus, when a user wants to find something he needs to type unless they are one of the first three. I'm still new to Javascript and I couldn't find an answer in other questions that helped. I've put my relevant code below. Thank you so much!!
HTML
<div class="field">
<%= f.label :homecity, "Home Town" %><br>
<%= f.select :homecity_id, Homecity.all.pluck(:Hometown, :id), {}, { class: "selectize1" } %>
</div>
Edit.js
$(document).on("turbolinks:load", function() {
var selectizeCallback = null;
$(".homecity-modal").on("hide.bs.modal", function(e) {
if (selectizeCallback != null) {
selectizeCallback();
selecitzeCallback = null;
}
$("#new_homecity").trigger("reset");
$.rails.enableFormElements($("#new_homecity"));
});
$(".selectize1").selectize({
create: function(input, callback) {
selectizeCallback = callback;
$(".homecity-modal").modal();
$("#homecity_Hometown").val(input);
}
})
});
selectize takes an option parameter for "maxOptions" that provides what you want.
for example:
$(“.selectize1”).selectize({maxOptions: 3});

Is Rails Collection_Select onchange still supported?

I'm trying to create a text field that is visible only when the user selects "Other" from a dropdown menu.
I've done this before with some jQuery and rails "select" but I haven't been able to get it working for "collection_select".
People say that onChange should work but so far I have had no luck.
Collection Select:
<%= f.collection_select(:professor, Professor.order(:fullname), :id, :fullname,
include_blank: false, :prompt => "Other", :onchange => "review_professor();")%>
<%= f.text_field :professor, class: "class-reveal", style: "display: none;"%>
Javascript:
review_professor = function() {
if(this.value == "Other") {
$('.class-reveal').show();
$('.class-reveal').val('');
}else{
$('.class-reaveal').hide();
$('.class-reveal').val(this.value);
}
});
Any ideas of why this is not working or another way I can do this? Is collection_select still supported?
It still works for collection_select, it just needs to go in the html_options hash, like so:
{include_blank: false, prompt: "Other"}, {onchange: "review_professor();"}

Show different controls depending on rails collection select (selected) item

Sorry i couldn't get a better title to my question but hope my explanation will give you guys a better idea of what's going on?
I have a model Airport and three other models West East and South that aren't related in anyway only that Airport model needs some of the other fields like this form shows.
<%= form_for(#airport) do %>
<%= f.collection_select(:airport_name, AirPortManager.all, etc...) %>
//AirPortManager is a collection of available airports
<div class="west-airports" style="display:none;">
<%= f.collection_select(:airline_name, WestAirlineManager.all, ....) %>
</div>
<div class="east-airports" style="display: none;">
<%= f.collection_select(:airline_name, EastAirlineManager.all, ....) %>
</div>
<div class="south-airports" style="display: none;">
<%= f.collection_select(:airline_name, EastAirlineManager.all, ....) %>
</div>
<% end %>
The airport model validates :airline_name, :presence => true . Now the problem is with
my javascript. If a user selects airport west in AirPortManager.all the west-airports div` should be shown and so on. But my validation method airport keeps throwing a required field error for :airline_name and if not that it keeps a value from a previous selection. How can i pass the visible div value to airport parameters or if i select an empty value the previous value shoudn't remain constant. Below is my javascript and hope my question makes sense.
<script type="text/javascript">
$(document).ready(function() {
$("#aiport_manager_aiport_name").change(function(){
var value = this.value;
if (value == "West") {
$('.west-aiports').show();
$('.east-airports').attr("disabled", true);
$('.east-airports').hide();
$('.south-airports').attr("disabled", true);
$('.south-airports').hide();
}
else if (value == "East") {
$('.east-airports').show();
$('.west-aports').hide();
$('.west-airports').attr("disabled", true);
$('.south-airports').hide();
$('.south-airports').attr("disabled", true);
}
else if (value == "South") {
$('.south-aiports').show();
$('.west-airports').hide();
$('.west-airports').attr("disabled", true);
$('.east-airports').hide();
$('.east-airports').attr("disabled", true);
}
});
});
</script>
I try and disable the other collection_selects in their respective divs but still get a validation error or get a persistent value.
Your form has multiple elements with the same name (:airline_name), which is the core problem. You're on the right track with disabling, but you're disabling the div instead of the select. I would just do this:
// before form is submitted, disable all hidden selects
$('form').on('submit', function(e) {
$('select:hidden').prop('disabled', true);
});

Categories

Resources