Search code examples
javascriptpythonflasklocal-storagejinja2

Flask keep option of selector selected when refresh


I'm looking for a way to keep an option of an html selector selected after user chooses one and refresh the page (GET request) or send data (POST request).

The only way that really seemed to work was using localstorage with JavaScript but it seems that it does not work with jinja (see an example below) :

  <select title='selector' id="interface-output" class="browser-default">
    <option id="select" value="select">Select an interface</option>
    {% for element in new_list %}
        <option value='{{ element }}'>{{ element }}</option>
    {% endfor %}

and the javascript script :

  document.getElementById('interface-output').onchange = function() {
    localStorage.setItem('selectedtem', document.getElementById('interface-output').value);
  };

  if (localStorage.getItem('selectedtem')) {
    document.getElementById('interface-output').options[localStorage.getItem('selectedtem')].selected = true;
  }

It works with fixed options but not with dynamic jinja2 ones like here. Do you have any other way to make it work ? Thanks in advance !


Solution

  • You can use local storage to choose the selected option value using Jinja 2 dynamic options.

    Here is a simple example of using local storage in the Jinja 2 select tag.

    app.py:

    from flask import Flask, request, render_template, flash
    
    app = Flask(__name__)
    app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
    
    
    @app.route('/add', methods=['GET', 'POST'])
    def add_product():
        options = ["Mobile", "Laptop", "Monitor"]
        if request.method == 'POST':
            product_name = request.form["product_name"]
            product_type = request.form["product_type"]
            flash(f'New product Added. Name: {product_name}, type: {product_type}')
        return render_template('dropdown.html', options=options)
    

    templates/dropdown.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Selected dropdown example</title>
    </head>
    <body>
    <h2>Add new product</h2>
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    <form action="{{ url_for('add_product') }}"
          method="post"
          id="product_form">
        <label for="product_type">Product type:</label>
        <select name="product_type" id="product_type">
            {% for element in options %}
            <option value='{{ element }}'>{{ element }}</option>
            {% endfor %}
        </select>
        <br>
        <label for="product_name">Product name</label>
        <input type="text" name="product_name" id="product_name">
        <br>
        <input type="submit" value="Save" id="save_btn">
    </form>
    <script>
        window.onload = function (event) {
            if (localStorage.getItem('selected_type')) {
                const selected_type = localStorage.getItem('selected_type');
                const dropdown = document.getElementById('product_type');
                for (let i = 0; i < dropdown.options.length; i++) {
                    if (dropdown.options[i].value === selected_type) {
                        dropdown.options[i].selected = true;
                        break;
                    }
                }
            }
        };
        const product_form = document.getElementById('product_form');
        const save_btn = document.getElementById('save_btn');
        save_btn.addEventListener('click', function (event) {
            event.preventDefault();
            const selected_type = document.querySelector('#product_type').value;
            localStorage.setItem('selected_type', selected_type);
            product_form.submit();
        });
    </script>
    </body>
    </html>
    

    Explanation:

    • First, we pass the options value from Flask to the template using options = ["Mobile", "Laptop", "Monitor"].
    • In the page load we check if there is any value set for local storage key selected_type. If there is any value set then we set the selected option value to true.
    • In form submit we prevent the submission and set the local storage for key selected_type to the selected product type and then we submit the form using form.submit() method.
    • We display the submitted form values using Flask's flash method.

    Demonstration

    • Initial view. By default the first item (Mobile) is selected as there are is no value in selected_type in local storage:

    initial

    • After selecting Laptop as a product type and submitting the form, the product type will remain Laptop:

    product_type

    References