Search code examples
javascripthtmlflaskjinja2bootstrap-selectpicker

How do i create multiple dynamic selectpicker based on my jinja for loop?


Currently, I am trying to create multiple dynamic select picker dropdown list based on user input. This input will be passed over to my HTML page via jinja in a for loop.

Based on the for loop, i will create the corresponding amount of dropdown list pairs.

On top of that, i also plan to reconfigure the id of each dropdown list so that i can easily retrieve their values in my Flask code. I tried writing for loops in javascript to modify the id.

I have tried to write some javascript to do those functions, but does not seemed to work. Not very familiar with javascript actually.

HTML Code

<form method="POST">
    {% for i in no_of_filters: %}
        <select id="col" class="selectpicker" onchange='refreshList(event,'{{ i+1|string }}')';>
            {% for c in cols: %}
                <option value="{{c}}">{{c}}</option>
            {% endfor %}
        </select>
        <select id ="val" class="selectpicker" multiple data-live-search="true">
            {% for uv in unique_val: %}
                <option value="{{uv}}">{{uv}}</option>
            {% endfor %}
        </select>
    {% endfor %}
    <input type="submit">
</form>
    <script>
        console.clear()

        var colElements = document.querySelectorAll('#col');
        var valElements = document.querySelectorAll('#val');

        for (var i = 0; i < colElements.length; i++)
            colElements[i].id = 'col' + (i+1);

        for (var j = 0; j < valElements.length; j++)   
            valElements[i].id = 'val' + (j+1);


        function refreshList(event, i){
            var col_select = document.getElementById('col'.concat(i));
            var uv_select = document.getElementById('val'.concat(i));

            column = col_select.value;

            fetch('/col/' + column).then(function(response) {
                response.json().then(function(data) {
                    var optionHTML = ' ';
                    for (var uv of data.unique_val) {
                        optionHTML += '<option value="' + uv.id + '">' + uv.value + '</option>';
                    }
                    uv_select.innerHTML = optionHTML;
                    $('#val'.concat(i)).on('change', function() {
                        $('#val'.concat(i)).selectpicker('refresh');
                    });
                })
            });
        }



    </script>

Expected: If no_of_filters = 7, the for loop should create 7 pairs of dynamic select picker dropdown fields, with configured ids by javascript

Actual: Only create 1 pair of select picker drop down lists, with no configured id


Solution

  • The select has the same id. Try to add diffrent id for each select like below:

    Html:

    <form method="POST">
    {% for i in no_of_filters: %}
        <select id="col-{{i}}" class="selectpicker col" 
        onchange='refreshList(event,'{{ i+1|string }}')';>
            {% for c in cols: %}
                <option value="{{c}}">{{c}}</option>
            {% endfor %}
        </select>
        <select id ="val-{{i}}" class="selectpicker val"
            multiple data-live-search="true">
            {% for uv in unique_val: %}
                <option value="{{uv}}">{{uv}}</option>
            {% endfor %}
        </select>
    {% endfor %}
    <input type="submit">
    </form>
    

    js:

    <script>
            console.clear()
    
            var colElements = document.querySelectorAll('select.col');
            var valElements = document.querySelectorAll('select.val');
    
            for (var i = 0; i < colElements.length; i++)
                colElements[i].id = 'col-' + (i+1);
    
            for (var j = 0; j < valElements.length; j++)   
                valElements[i].id = 'val-' + (j+1);
    
    
            function refreshList(event, i){
                var col_select = document.getElementById('col-'.concat(i));
                var uv_select = document.getElementById('val-'.concat(i));
                // same logic
            }
    
    
    
        </script>