Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

viktor3177's avatar

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

There is a form! It has a select in which, when choosing the right service, the necessary fields appear - everything works as it should here!

<div class="form-group">
	<label>Select other type of Service</label>
	<div class="ors-custom-select">
		<select  id="service" type="text" class="form-control required" placeholder="Service type" aria-required="true" name="service_type">
			<option value="">Other type of Service</option>
			<option class="js-show-prod js-show-prod2" value="Hourly/As Directed">Hourly/As Directed</option>
			<option class="js-show-prod2" value="To Airport">To Airport</option>
			<option class="js-show-prod1" value="From Airport">From Airport</option>
			<option class="js-show-prod2" value="Point-to-Point Transfer">Point-to-Point Transfer</option>
			<option class="js-show-prod2" value="Other">Other</option>
		</select>
	</div>
</div>
<div class="form-group">
	<!--Drop-Off Location-->
	<div id="pickup_airport" style="display: none;" wfd-invisible="true">
		<div class="form-group ors-autocomplete-wrap ors-autocomplete-wrap-lg">
			<label for="address2" class="control-label autocomplete-label">* Pick-Up Location</label>
			<div class="ors-autocomplete">
				<input id="address2" ref="locationRef" type="text" autocomplete="off" class="form-control form-control-2 required required_s pac-target-input" placeholder="* Your pick-up location" name="pick_up_location_hr" aria-required="true" autocomplete="off">
			</div>
		</div>
	</div>
	<div id="pickup_hr" style="display: none;">
		<div class="form-group">
					<label for="pickup_hr">Number of Hours</label>
					<div class="input-group">
					<span class="input-group-text"><i class="fas fa-clock"></i></span>
						<input id="pickup_hr" type="number" min="3" class="form-control form-control-2 required required_s pac-target-input" placeholder="*Number of Hours (3Hrs Minimum)" name="pickup_hr" aria-required="true" min="1" step=".1">
					</div>
		</div>
	</div>
	<!--Drop-Off Location-->
	<div class="form-group ors-autocomplete-wrap ors-autocomplete-wrap-lg">
		<label for="address4" class="control-label autocomplete-label">Drop-Off Location </label>
		<div class="ors-autocomplete">
			<input id="address4" ref="drop_off_locationRef" type="text" autocomplete="off" class="form-control form-control-2 required required_s pac-target-input" placeholder="*Your drop-off location" name="drop_off_location" aria-required="true" autocomplete="off">
		</div>
	</div>
</div>

Script

<script type="text/javascript">
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod" );
		document.getElementById('pickup_hr').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod" );
		document.getElementById('pickup_airport').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod1" );
		document.getElementById('pickup_street').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod2" );
		document.getElementById('pickup_airport').style.display = isPear ? "block" : "none";
	});
</script>

There is also a similar select where there is also a service and the choice does not work here.

<div class="form-group">
	<label>Select Return other type of Service</label>
	<div class="ors-custom-select">
		<select  id="service_return" type="text" class="form-control required" placeholder="Service type" aria-required="true" name="service_type_return">
			<option value="">Other type of Service</option>
			<option class="js-show-prod0 js-show-prod20" value="Hourly/As Directed">Hourly/As Directed</option>
			<option class="js-show-prod20" value="To Airport">To Airport</option>
			<option class="js-show-prod10" value="From Airport">From Airport</option>
			<option class="js-show-prod20" value="Point-to-Point Transfer">Point-to-Point Transfer</option>
			<option class="js-show-prod20" value="Other">Other</option>
		</select>
	</div>
</div>

<div class="form-group">
	<!--Drop-Off Location-->
	<div id="pickup_airport_return" style="display: none;" wfd-invisible="true">
		<div class="form-group ors-autocomplete-wrap ors-autocomplete-wrap-lg">
			<label for="address2_return" class="control-label autocomplete-label">* Return Pick-Up Location</label>
			<div class="ors-autocomplete">
				<input id="address2_return" ref="locationRef" type="text" autocomplete="off" class="form-control form-control-2 required required_s pac-target-input" placeholder="* Your pick-up location" name="pick_up_location_hr_return" aria-required="true" autocomplete="off">
			</div>
		</div>
	</div>
	<div id="pickup_hr_return" style="display: none;">
		<div class="form-group">
			<label for="pickup_hr1">Number of Hours</label>
			<div class="input-group">
				<span class="input-group-text"><i class="fas fa-clock"></i></span>
				<input id="pickup_hr1" type="number" min="3" class="form-control form-control-2 required required_s pac-target-input" placeholder="*Number of Hours (3Hrs Minimum)" name="pickup_hr_return" aria-required="true" min="1" step=".1">
			</div>
		</div>
	</div>
	<!--Drop-Off Location-->
	<div class="form-group ors-autocomplete-wrap ors-autocomplete-wrap-lg">
		<label for="address4_return" class="control-label autocomplete-label">Return Drop-Off Location </label>
		<div class="ors-autocomplete">
			<input id="address4_return" ref="drop_off_locationRef" type="text" autocomplete="off" class="form-control form-control-2 required required_s pac-target-input" placeholder="*Your drop-off location" name="drop_off_location_return" aria-required="true" autocomplete="off">
		</div>
	</div>
</div>

Script

<script type="text/javascript">
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod0" );
		document.getElementById('pickup_hr_return').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod0" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod10" );
		document.getElementById('pickup_street_return').style.display = isPear ? "block" : "none";
	});
</script>
<script type="text/javascript">
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod20" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});
</script>

But an error appears in the console (Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')).

0 likes
15 replies
rodrigo.pedra's avatar

where are you adding these script tags?

As you are not wrapping then on a listener for the DOMContentLoaded event, they should be placed at the very bottom of your HTML, right before you close your <body> tag.

If they are added to the <head> element, as it is now, the DOM won't be available, so no elements will exist to be queried with getElementById()

As you are using inline JavaScript code, adding the defer attribute will not help, so be sure these script tags are the very last thing on your rendered HTML.

reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer

Sinnbeck's avatar

@viktor3177 you shouldn't add the exact same event listener to the same item over and over. Just have 1 script with 1 event listener for each id

Sinnbeck's avatar

@viktor3177 just 1 script tag is needed

<script type="text/javascript">
document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod10" );
 document.getElementById('pickup_street_return').style.display = isPear ? "block" : "none";
  //rest of logic that is related to this change event 
})
</script>

But it seems you have several things that change the same item?

viktor3177's avatar

@Sinnbeck Yes there is. In some options, other fields appear. Therefore, there are different classes.

Sinnbeck's avatar

@viktor3177 I'm not sure what you mean?

Example

document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod20" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});

And this

document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod0" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});

Does exactly the same and at the same time (change event on #service_return).

viktor3177's avatar

@Sinnbeck

I have now rewritten it. But // Ride Info works as it should, and // Return Trip still doesn't work.

<script type="text/javascript">
	// Ride Info
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod" );
		document.getElementById('pickup_hr').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod" );
		document.getElementById('pickup_airport').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod1" );
		document.getElementById('pickup_street').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod2" );
		document.getElementById('pickup_airport').style.display = isPear ? "block" : "none";
	});
	// Return Trip
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod0" );
		document.getElementById('pickup_hr_return').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod0" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod10" );
		document.getElementById('pickup_street_return').style.display = isPear ? "block" : "none";
	});
	document.getElementById('service_return').addEventListener('change', function(){
		let isPear = this.options[this.selectedIndex].classList.contains("js-show-prod20" );
		document.getElementById('pickup_airport_return').style.display = isPear ? "block" : "none";
	});
</script>
Sinnbeck's avatar

@viktor3177 you still have multiple listeners on the same select. And code that tries to change the same div at the same time

viktor3177's avatar

@Sinnbeck

Why does (// Ride Info) work then? The class is different because it stands between the directions?

viktor3177's avatar

Does anyone else have any ideas to make this problem work? :(

rodrigo.pedra's avatar

@viktor3177 well your problem is that your mixing Vue with plain JavaScript

Open the inspector and search for service_return, you won't find any element. Not the view source, the inspector which represents the current DOM.

This <select> element is nested inside v-for that only adds any element to the DOM when you click a link labeled "+ Return trip"

So before any "return trip" is added, there is simply no element with id="service_return" added to the DOM.

As you are already using Vue, why don't you add those listeners on Vue directly?

rodrigo.pedra's avatar

@viktor3177

I'd use Vue to add this listeners you need.

Laracasts has a free Vue series in case you are not familiar with Vue:

https://laracasts.com/series/learn-vue-3-step-by-step

I am sorry, but code on the page you shared is too long and convoluted to give you more than an advice on learning Vue.

Finding out the issue was already a larger task than usual for a support forum's answer.

Good luck =)

Please or to participate in this conversation.