skip to Main Content

I have two selectpicker. One for city and other for towns. When citySelectpicker changes I load towns with AJAX.

There is no problem with this. When I try to get on change event on TownSelect nathing happens. TownSelect onchange not working.

But I refresh page. And directly change the townSelect Change event works. but before it I use CityChange it is not work.

index.php

<!DOCTYPE html>
<html lang="en" class="no-js">

<head>

    <meta charset="UTF-8">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/bootstrap-select.css" />
    <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
    <script src="js/bootstrap-select.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
    <link rel="stylesheet" href="css/jquery-ui.css">

    <?php
    header("Cache-Control: no cache");
    ?>

</head>


<body>

<div class="cityList col-lg-3 col-md-6 col-sm-3">
    <label for="citySelect2" class="labelsfilter ml-2">City</label>
    <select class="selectpicker mb-3" id="citySelect2" name="citySelect2" data-width="100%" data-live-search="false" required="required">
        <option value="">Select City</option>
    <?php
    $myQuery = "SELECT * FROM tessCityTable";
    $statement = $konn->prepare($myQuery);
    $statement->execute();
    $results = $statement->fetchAll(PDO::FETCH_ASSOC);
    if ($results){
        foreach ($results as $result){
            if (isset($cityID2)){
                if ($cityID2 == $result['cityID']){
                    echo ('<option value="'.$result['cityID'].'" selected>'.$result['cityName'].'</option>');
                }
                else {
                    echo ('<option value="'.$result['cityID'].'">'.$result['cityName'].'</option>');
                }
            }
            else {
                echo ('<option value="'.$result['cityID'].'">'.$result['cityName'].'</option>');
            }
            
        }
    }

    ?>
    </select>
</div>                  

<div id="townList2" class="townList2 col-lg-3 col-md-6 col-sm-3">
    <label for="townSelect2" class="labelsfilter ml-2">Town</label>
    <select class="selectpicker mb-3 show-tick townSelect2" id="townSelect2" name="townSelect2[]" multiple="multiple" data-live-search="false" data-width="100%" data-selected-text-format="count">
        <option value="0">Select Town</option>
    </select>
</div>

</body>

</html>

<script>            
$(document).ready(function() {
    $('#townSelect2').selectpicker();

    $("#citySelect2").change(function() {
        var selectedCity = $(this).val();

        $.ajax({
            type: "POST",
            url: "query.php",
            data: 'keyword=' + selectedCity,
            success: function(data) {
                var response = JSON.parse(data);

                $('.townList2').html(response.townList);
                $('.townSelect2').selectpicker('refresh');

            }
        });
    });

    $('#townSelect2').on('changed.bs.select', function(e) {
        //Nothing Happens
            console.log("changed.bs.select event triggered");
            console.log("e:", e);
        
    });


    $("#townSelect2").change(function() {
        //Nothing Happens
        console.log("changeEvent");
    });

})

</script>

And query.php

if (!empty($_POST["keyword"])) {
    $townList = "";
    $cityID = $_POST['keyword'];
    $myQuery = "SELECT * FROM tessTownTable WHERE cityID=:cityID";
    $statement = $konn->prepare($myQuery);    
    $statement->bindParam(':cityID', $cityID);
    $statement->execute();
    $result = $statement->fetchAll(PDO::FETCH_ASSOC);
    if (!empty($result)) {
        
        $townList = $townList . '<label for="townSelect2" class="labelsfilter ml-2">İlçe</label>';
        $townList = $townList . '<select class="selectpicker mb-3 show-tick townSelect2" id="townSelect2" name="townSelect2[]" multiple="multiple" data-live-search="false" data-width="100%" data-selected-text-format="count">';
        $townList = $townList . '<option value="0">İlçe Seçiniz</option>';
  
        foreach ($result as $town) { 
            $townList = $townList . '<option value="'.$town['townID'].'">'.$town['townName'].'</option>';
        }
        $townList = $townList . '</select>';

        $konn = null;
        $statement = null;

        $response = array(
            "townList" => $townList
        );
        
        $jsonResponse = json_encode($response);

        echo $jsonResponse;  
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Here is an answer. But I really dont want to use obServer. but cant find any solution If I find anything without obServer I will update the answer.

    Please check the Javascript part.

        <!DOCTYPE html>
    <html lang="en" class="no-js">
    
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="css/bootstrap-select.css" />
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
        <script src="js/bootstrap-select.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
        <link rel="stylesheet" href="css/jquery-ui.css">
        <?php
        header("Cache-Control: no cache");
        ?>
    </head>
    
    <body>
    
        <div class="cityList col-lg-3 col-md-6 col-sm-3">
            <label for="citySelect2" class="labelsfilter ml-2">City</label>
            <select class="selectpicker mb-3" id="citySelect2" name="citySelect2" data-width="100%" data-live-search="false" required="required">
                <option value="">Select City</option>
                <?php
                $myQuery = "SELECT * FROM tessCityTable";
                $statement = $konn->prepare($myQuery);
                $statement->execute();
                $results = $statement->fetchAll(PDO::FETCH_ASSOC);
                if ($results) {
                    foreach ($results as $result) {
                        if (isset($cityID2)) {
                            if ($cityID2 == $result['cityID']) {
                                echo ('<option value="' . $result['cityID'] . '" selected>' . $result['cityName'] . '</option>');
                            } else {
                                echo ('<option value="' . $result['cityID'] . '">' . $result['cityName'] . '</option>');
                            }
                        } else {
                            echo ('<option value="' . $result['cityID'] . '">' . $result['cityName'] . '</option>');
                        }
                    }
                }
                ?>
            </select>
        </div>
    
        <div id="townList2" class="townList2 col-lg-3 col-md-6 col-sm-3">
            <label for="townSelect2" class="labelsfilter ml-2">Town</label>
            <select class="selectpicker mb-3 show-tick townSelect2" id="townSelect2" name="townSelect2[]" multiple="multiple" data-live-search="false" data-width="100%" data-selected-text-format="count">
                <option value="0">Select Town</option>
            </select>
        </div>
    
        <script>
            $(document).ready(function() {
                $('#townSelect2').selectpicker();
    
                $("#citySelect2").change(function() {
                    var selectedCity = $(this).val();
    
                    $.ajax({
                        type: "POST",
                        url: "query.php",
                        data: 'keyword=' + selectedCity,
                        success: function(data) {
                            var response = JSON.parse(data);
    
                            $('.townList2').html(response.townList);
                            $('#townSelect2').selectpicker('refresh');
    
                            $('#townSelect2').on('changed.bs.select', function(e) {
                                console.log("changed.bs.select event triggered");
                                console.log("e:", e);
                            }).trigger('change'); 
    
                        }
                    });
                });
    
                $("#townSelect2").change(function() {
                    console.log("changeEvent");
                });
    
                
                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        if (mutation.type === "childList" && mutation.target.id === "townSelect2") {
                            console.log("townSelect2 DOM değişikliği");
                            console.log(mutation);
                        }
                    });
                });
    
                
                observer.observe(document.getElementById("townSelect2"), {
                    childList: true, 
                    subtree: true 
                });
    
            });
        </script>
    
    </body>
    
    </html>
    

  2. [TL:DR]:

    swap

    $('#townSelect2').on('changed.bs.select', function() {...})
    

    with

    $('body').on('changed.bs.select', '#townSelect2', function() {...})
    

    and use

    $('.townList2').replaceWith(response.townList);
    

    instead of

    $('.townList2').html(response.townList);
    

    You need to use event delegation in order to use an event on a dynamically added element like your townSelect2 – select.

    Explanation:

    If you attach an event handler for the changed.bs.select– event to all elements with the id townSelect2 that event will get attached to all elements with the id townSelect2 that are present in the DOM when the script is being loaded. That means, that you have to either attach the event again when you dynamically add an element to the DOM, like you do in your ajax success, or that you need to delegate the event to a parent element that in fact is present when your DOM loads.

    /* Attach the event to the body (or any other parent element of your select)
      the event will then bubble up until it "finds" the element with the 
      townSelect2 id and trigger */
    $('body').on('changed.bs.select', '#townSelect2', function() {...})
    

    Also, you are returning a completed <select> ELement from your PHP endpoint, but you are inserting it in your current <select>selemt with .html(...). You need to replace it, in order to prevent invalid HTML like this :

    <select class="..." id="..."><select class="..." id="...">...</select></select>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search