Reputation: 488
I have a select box populated from a JSON file, I want to reload the URL but pass the value from the select box.
Here is a cut down version of my index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Timetables</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div id="navbar" class="navbar-collapse collapse">
</div>
<!--/.navbar-collapse -->
</div>
</nav>
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<div id="headerArea">
</div>
</div>
</div>
</body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
var $crs = GetURLParameter('crs');
// Function that uses this variable removed as not relevant
$.getJSON('csr.json', function (data) {
var stationDropdown = '<form class="navbar-form navbar-right" action="">';
stationDropdown += '<select class="form-control" id="stations">';
for (var i in data) {
stationDropdown += '<option value="' + data[i].Code + '">' + data[i].StationName + '</option>';
}
stationDropdown += '</select>';
stationDropdown += '</form>';
$("#navbar").html(stationDropdown);
});
$(function(){
// bind change event to select
$('#stations').bind('change', function () {
var url = $(this).val(); // get selected value
if (url) { // require a URL
window.location = 'index.html?crs='.url; // redirect
}
return false;
});
});
</script>
</html>
and here is a sample of the JSON
[
{
"StationName":"Abbey Wood",
"Code":"ABW"
},
{
"StationName":"Aber",
"Code":"ABE"
}
]
The select box generates fine and is 'injected(?) into the navbar div, but the on change event wont register
Basically if someone was to select Aber, the onchange event will reload index.html?crs=ABE automatically.
Dev tools is not throwing up any errors, its just not doing anything when I change the select box.
I suspect I need to run the on change event as a function that is called exclusively when needed as putting it in at the bottom of the index.html file means its loading before the DOM is ready?
Thanks in advance for any assistance.
Upvotes: 1
Views: 1280
Reputation: 920
You should move all of your HTML building INTO the HTML.
Inside of your getJSON()
you can cut that code down to this:
var stations = $( '#stations' );
for (var i in data) {
stations.append( '<option value="' + data[i].Code + '">' + data[i].StationName + '</option>' );
}
Once you do that, everything else should work appropriately. Here's what I changed in your HTML:
<div id="navbar" class="navbar-collapse collapse">
<form class="navbar-form navbar-right" action="">
<select class="form-control" id="stations">
<option>Select One</option>
</select>
</form>
</div>
Also, as a note. jQuery recommends using the on()
method instead of the bind()
method as of 1.7.
Upvotes: 1
Reputation: 327
It's because the $.getJSON function is called after the $(function(){ If you move the code in $(function(){, to the end of the $.getJSON function, then it'll work.
Upvotes: 1
Reputation: 26370
Always the same question... you initiate your bind event before the dropdown is created, because it depends on an ajax call.
What's wrong with your code :
$.getJSON('csr.json', function (data) { // This is done #1
.......
$("#navbar").html(stationDropdown); // this is done #3 : creating #stations.
});
$('#stations').bind('change', function () { // This is done #2 and won't do anything because #stations doesn't exist yet
........
});
The right way is :
$.getJSON('csr.json', function (data) { // This is done #1
.......
$("#navbar").html(stationDropdown); // this is done #2 : creating #stations.
$('#stations').bind('change', function () { // This is done #3
........})
});
Upvotes: 1
Reputation: 133403
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
As you are creating elements dynamically.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
General Syntax
$(document).on(event, selector, eventHandler);
Ideally you should replace document
with closest static container.
Example
$("#navbar").on('change', '#stations', function(){
//Your code
});
Upvotes: 1
Reputation: 104775
You need to use on
for dynamic content:
$('#navbar').on('change', '#stations', function () {
^ Static container content is appended to
^ #stations = target element
Upvotes: 0