MOLEDesign
MOLEDesign

Reputation: 488

Change URL based on change of dynamic select box

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

Answers (5)

Matt Wagner
Matt Wagner

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.

http://api.jquery.com/bind/

Upvotes: 1

Simon Sawyer
Simon Sawyer

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

Jeremy Thille
Jeremy Thille

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

Satpal
Satpal

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

tymeJV
tymeJV

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

Related Questions