Search code examples
javascriptpythonjqueryflask

Select option depent on a other selected parent option in same page


I have a page with two selection fields. Project selection and company selection.

Existing Data for the fields. Bold are the projects, Italic the companies.

ASAS --Fa_Test

DATA --Fa_Test0, --Fa_Test1, --Fa_Test2

ELTC --Fa_Test3, --Fa_Test4

First view when page is loaded. enter image description here

View when the first project is selected. enter image description here There is only one company as standard and it cannot be changed (Text input field)

View when another project is selected. enter image description here

The company selection field only appears when a project selection has been made in the first field with the following query.

<script>
$(function () {
    $("#project_ou").on( "change", function () {
        // ASAS
        if ($(this).val() == "empty") {
            $("#company_select").hide();
            $("#Other").hide();
        } if ($(this).val() ==  "ASAS"){
            $("#Other").show();
            $("#company_select").hide();
        } if ($(this).val() != "ASAS"){
            $("#company_select").show();
            $("#Other").hide();
        }
    });
});
</script>

The companies selection should be displayed depending on the project and without reloading the page.

The data is passed to the page with the following python code:

...
...
return render_template('portal/prov_new_device_first.html',
                      projects=projects,
                      companies=companies)

The html page part on the prov_new_device_first.html looks like this:

<div class="callout callout-warning">
     <label>Please select a Project or Division.</label><br>
     <div class="form-group">
         <select name="project_ou" class="select_proj form-control" id="project_ou">
             <option value="empty" selected>- - Select from the list - -</option>
                {% for project in projects %}
                    <option value="{{ project.name }}" id="{{ project.name }}">{{ project.name }}</option>
                {% endfor %}
        </select>
    </div>
    <div class="form-group" id="Other" style="display:none;">
        <label for="txtReason">Division (Standard)</label><br>
            {% for company in companies %}
               {% if company.destinationindicator == "ASAS" %}
                  <input type="text" value="{{ company.name }}" class="form-control" name="txtReason" disabled>
               {% endif %}
            {% endfor %}
    </div>
    <div class="form-group" id="company_select" style="display:none;">
        <label for="companyname">Please select the company where the Bootstick will be added.</label><br>
            <select name="companyname" class="form-control select_proj" id="companyname">
                <option selected>- - Select a Company</option>
                    {% for company in companies %}
                       {% if company.destinationindicator == project.name %}
                          <option value="{{ company.name }}" id="{{ company.name }}">{{ company.name }}</option>
                       {% endif %}
                    {% endfor %}
            </select>
     </div>
</div>

How can I select the correct project depent company data when I select a project?

I spent a lot of time with many options trying to transfer the project name to this place, but it did not work.

{% if company.destinationindicator == project.name %}

The destinationindicator in the company attributes contains the dependent project name.

Does anyone have any ideas on how to solve this?

Thanks in advance.


Solution

  • Code {% if company.destinationindicator == project.name %} should be executed
    in {% for project in projects %} to work.

    But this code is executed on server before it sends HTML to browser - so it is useless for this problem.

    You have to use JavaScript for this problem.

    JavaScript can do one of things:

    • replace all <option> with companies when you select project - but it may need a lot code and it needs to keep all data in JavaScript.
    • use company.destinationindicator as class in <option> and later it can hide all <option> and show only <option> which have class with selected project.name

    This code adds all companiesto <option> with company.destinationindicator as class

    <option selected>- - Select a Company</option>
    {% for company in companies %}
    <option value="{{ company.name }}" id="{{ company.name }}" class="{{ company.destinationindicator }}">{{ company.name }}</option>
    {% endfor %}
    

    And this code hides all <option> and later shows only <option> with class which has name of selected project

        } if ($(this).val() != "ASAS"){
            $("#company_select").show();
            $("#Other").hide();
        
            $("#company_select option").hide();                // hide all `option`
            $("#company_select option."+$(this).val()).show(); // show only options with selected project name
        }
    

    Minimal working code with fake data for tests.

    I use render_template_string instead of render_template so everyone can easily copy it to one file for tests.

    HTML = """   
    <!DOCTYPE html>
    <html>
    <head>  
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
         <script>
    $(function () {
        $("#project_ou").on( "change", function () {
            // ASAS
            if ($(this).val() == "empty") {
                $("#company_select").hide();
                $("#Other").hide();
            } if ($(this).val() == "ASAS"){
                $("#Other").show();
                $("#company_select").hide();
            } if ($(this).val() != "ASAS"){
                $("#company_select").show();            
                $("#Other").hide();
                
                $("#company_select option").hide();                // hide all `option`
                $("#company_select option."+$(this).val()).show(); // show only `option` with selected `project name` as `class`
            }
        });
    });
    </script>
    </head>
    <body>            
    <div class="callout callout-warning">
         <label>Please select a Project or Division.</label><br>
         <div class="form-group">
             <select name="project_ou" class="select_proj form-control" id="project_ou">
                 <option value="empty" selected>- - Select from the list - -</option>
                    {% for project in projects %}
                        <option value="{{ project.name }}" id="{{ project.name }}">{{ project.name }}</option>
                    {% endfor %}
            </select>
        </div>
        <div class="form-group" id="Other" style="display:none;">
            <label for="txtReason">Division (Standard)</label><br>
                {% for company in companies %}
                   {% if company.destinationindicator == "ASAS" %}
                      <input type="text" value="{{ company.name }}" class="form-control" name="txtReason" disabled>
                   {% endif %}
                {% endfor %}
        </div>
        <div class="form-group" id="company_select" style="display:none;">
            <label for="companyname">Please select the company where the Bootstick will be added.</label><br>
                <select name="companyname" class="form-control select_proj" id="companyname">
                    <option selected>- - Select a Company</option>
                    {% for company in companies %}
                    <option value="{{ company.name }}" id="{{ company.name }}" class="{{ company.destinationindicator }}">{{ company.name }}</option>
                    {% endfor %}
                </select>
         </div>
    </div>
    </body>
    </html>
    """
    
    import os
    from flask import Flask, request, render_template_string
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        projects = [
            {'name':'ABC'}, 
            {'name':'DEF'}, 
            {'name':'XYZ'}, 
            {'name': 'ASAS'}
        ]
        companies = [
            {'name':'ASAS_001', 'destinationindicator':'ASAS'},
            {'name':'ABC_001', 'destinationindicator':'ABC'},
            {'name':'ABC_002', 'destinationindicator':'ABC'},
            {'name':'DEF_001', 'destinationindicator':'DEF'},
            {'name':'DEF_002', 'destinationindicator':'DEF'},
            {'name':'XYZ_001', 'destinationindicator':'XYZ'},
            {'name':'XYZ_002', 'destinationindicator':'XYZ'},
            {'name':'XYZ_003', 'destinationindicator':'XYZ'},
        ]
        return render_template_string(HTML, projects=projects, companies=companies)
    
    if __name__ == '__main__':
        app.debug = True 
        app.run()