Issue:
I am trying to do a simple javascript to show a <div>
if a radio button is marked as 'yes', and hide if it is marked as 'no'. The javascript works when I put it in my application template <head>
file, but not when I put it in an external .js file. I checked the compiled application.js and the code shows up, so I know that my external .js is being loaded in the asset pipeline.
Error Messages
The error that I get on window load in the console is:
Uncaught TypeError: Cannot read property 'checked' of null
at locationPicked (intake.js:3)
at Object../app/javascript/custom/intake.js (intake.js:1)
at __webpack_require__ (bootstrap:19)
at Module.<anonymous> (application.js:18)
at Module../app/javascript/packs/application.js (application.js:18)
at __webpack_require__ (bootstrap:19)
at bootstrap:83
at bootstrap:83
The error I get when clicking the 'Yes' Button is this:
Uncaught ReferenceError: locationPicked is not defined
at HTMLInputElement.onclick
Code
Here are the versions of ruby and the primary gems from the Gemfile:
ruby '2.6.2'
gem 'rails', '~> 6.0.2.2'
gem 'pg', '>= 1.1.4', '< 2.0'
gem 'puma', '~> 4.2.1'
gem 'sass-rails', '~> 6.0.0'
gem 'webpacker', '~> 4.0.7'
gem 'uglifier', '>= 4.2.0'
gem 'coffee-rails', '~> 5.0'
gem 'turbolinks', '~> 5.2.1'
gem 'jbuilder', '~> 2.9.1'
gem 'bootsnap', '>= 1.4.5', require: false
Here is my HTML and Ruby for the radio button:
# app/views/events/intake.html.erb
<h2 style="text-decoration:underline; padding: 50px 0 25px 0;">Step 2 - Location</h2>
<div style="font-size: 1.5rem; padding: 0 0 15px 0;">
Location Picked:
<%= f.radio_button :location_picked, 'yes', onClick: "locationPicked()" %>
<%= label :location_picked_yes, 'Yes' %>
<%= f.radio_button :location_picked, 'no', onClick: "locationPicked()" %>
<%= label :location_picked_no, 'No' %>
</div>
<div class="row" id="LocationSelection" style="display:none">
<div class="col-5">
<div class="card bg-light">
<div class="card-header text-center"><h4>Select a Location</h4></div>
<div class="card-body">
<h5 class="card-title"><%= f.label :location_id, for: "location_id" %></h5>
<%= f.select :location_id, options_for_select(@locations, :selected => @selected_loc),{class: "custom-select"}, id:"location_id", class: "custom-select" %>
</div>
</div>
</div>
<div class="col-1">
<h4 class="text-center">OR</h4>
</div>
<div class="col-6">
<div class="card bg-light">
<div class="card-header text-center"><h4>Create a new Location</h4></div>
<div class="card-body">
<h5 class="card-title">Location Name</h5>
<%= f.text_field :location_name, class: "form-control", type:"text", id:"org_name" %>
</div>
</div>
</div>
</div>
The resulting HTML that the browser sees is this:
// Browser --> View Source
<h2 style="text-decoration:underline; padding: 50px 0 25px 0;">Step 2 - Location</h2>
<div style="font-size: 1.5rem; padding: 0 0 15px 0;">
Location Picked:
<input onClick="locationPicked()" type="radio" value="yes" name="event[location_picked]" id="event_location_picked_yes" />
<label for="location_picked_yes_Yes">Yes</label>
<input onClick="locationPicked()" type="radio" value="no" name="event[location_picked]" id="event_location_picked_no" />
<label for="location_picked_no_No">No</label>
</div>
<div class="row" id="LocationSelection" style="display:none">
<div class="col-5">
<div class="card bg-light">
<div class="card-header text-center"><h4>Select a Location</h4></div>
<div class="card-body">
<h5 class="card-title"><label for="location_id">Location</label></h5>
<select id="location_id" class="custom-select" name="event[location_id]"><option value="4">Helping Hands - Warehouse</option>
<option value="3">New City Church - College Room</option>
<option value="1">Samaritan Bags - Place Holder</option></select>
</div>
</div>
</div>
<div class="col-1">
<h4 class="text-center">OR</h4>
</div>
<div class="col-6">
<div class="card bg-light">
<div class="card-header text-center"><h4>Create a new Location</h4></div>
<div class="card-body">
<h5 class="card-title">Location Name</h5>
<input class="form-control" type="text" id="org_name" name="event[location_name]" />
</div>
</div>
</div>
</div>
Here is the javascript file:
// app/javascript/custom/intake.js
window.onload = locationPicked();
function locationPicked() {
if (document.getElementById("event_location_picked_yes").checked) {
document.getElementById("LocationSelection").style.display = "block";
}
else document.getElementById("LocationSelection").style.display = "none";
}
Here is my application.js:
// app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require('jquery')
import '../stylesheets/application'
import 'bootstrap'
document.addEventListener("turbolinks:load", () => {
$('[data-toggle="tooltip"]').tooltip()
$('[data-toggle="popover"]').popover()
})
// Custom Scripts
require("custom/global")
require("custom/intake")
When loading the javascript the way listed above, the errors happen. When I use the javascript like this in my application template <head>
section it works:
// app/views/layouts/application.html.erb
<script type="text/javascript">
function locationPicked() {
if (document.getElementById("event_location_picked_yes").checked) {
document.getElementById("LocationSelection").style.display = "";
}
else document.getElementById("LocationSelection").style.display = "none";
}
</script>
Question
My javascript is very rusty. Any help here would be appreciated. Am I not calling the function correctly? I would think maybe a typo, but the code works in the <head>
section, so I think I ruled that out. Thank you in advance for your assistance.