3

I have a web form created that requires template creation by the user. Calling all previous entries that are templates isn't an issue, but passing the information to the form when called seems to be tricky. Basically I want the user to be able to select a template from the dropdown (See the screenshots and stuff below), then based on their selection, update the variables in the script to autofill form data. Right now, it only selects the most recent entry. Is this possible just using python/flask/javascript or am I missing something? Any help would be appreciated! Thanks!

Template Dropdown

    <label for="template_select">Select Template</label>
<select class="form-control" name="template_select" id='template_select' onchange='changeTemplate()'>
<option value=''></option>

{% for template_info in template_search %}
<option value='{{template_info.client_name}}'>{{template_info.client_name}}</option>
{% endfor %}

</select>

Javascript to change values

{% for template_info in template_search %}

<script>
function changeTemplate(){
    var template = document.getElementById('template_select').value;
    document.getElementById('client_name').value='{{template_info.client_name}}';
    document.getElementById('client_name').innerHTML='{{template_info.client_name}}';
}
</script>

{% endfor %}

Python Passing in the Query

template_search = newmatter_model.NewClientMatter.query.filter_by(
            creator=verifier, is_template='on').all()
3
  • It's not clear to me what you are trying to accomplish. Why is the script in a loop in the template? Commented May 24, 2018 at 13:51
  • What do you expect {{template_info.client_name}} in the Javascript code to resolve to? Your dropdown menu is populated from the template_search sequence, so there are multiple. Flask with Jinja produces a page that is sent to the browser. Once in the browser, Jinja is no longer involved, all that is sent is the text Jinja generated. The Javascript code runs in the browser without further connection. Commented May 24, 2018 at 13:57
  • 1
    Putting multiple definitions of the changeTemplate() function in the browser means that the browser will replace any definitions with the next one, so you have only one definition of changeTemplate(). You want to use Javascript to get the template_info.client_name value from the dropdown menu instead. You already did this (and put it in the template variable, but you then ignore that variable entirely. Commented May 24, 2018 at 13:59

1 Answer 1

3

Your mistake is to create Javascript code in a loop. You don't need to do this.

What you want to do is think of the data sent to the browser as independent. Make it work first without Flask and Jinja2. Create a static page that works and does what you want.

The following code would work with static data:

function changeTemplate(){
    var template = document.getElementById('template_select').value;
    document.getElementById('client_name').innerHTML = template;
}
<label for="template_select">Select Template</label>
<select class="form-control" name="template_select" id="template_select" onchange="changeTemplate()">
<option value=""></option>

<option value="Client 1">Client 1</option>
<option value="Client 2">Client 2</option>
<option value="Client 3">Client 3</option>
</select>

<div id="client_name"><i>No client set</i></div>

That's HTML for a select box, a separate <div> element, and Javascript code to copy the selected option value into the <div>. Note that the Javascript code doesn't know anything about what data is involved; no client names are stored in the code. All that the small function does is to copy the value from the currently selected option, to somewhere else.

Once that works on its own you can start thinking about how you are going to insert the values from your application. In the above code, all that needs replacing is the dropdown options, because the Javascript code can then access everything it needs from the <select> element value.

So the Javascript code doesn't need to be generated at all, you only generate the <option> elements, as you already did in your question.

You rarely need to generate dynamic Javascript code, and it would be much better for your app if you don't. Static Javascript code can be served by a CDN and cached in the browser, removing the need for your app to keep serving that again and again for all clients. Try to minimise that whenever you can.

Instead, generate just the data that the code needs to operate on.

  • You can put that information in HTML tags. In the above example, your data is put in the repeated <option> tags. Or
  • you could add data attributes to your HTML, which are accessible both to Javascript code and to CSS. Or
  • use AJAX to load data asynchronously; e.g. when you pick an option in the <select> box, use Javascript and AJAX to call a separate endpoint on your Flask server that serves more data as JSON or ready-made HTML, then have the Javascript code update your webpage based on that. Or
  • generate JSON data and put it directly into your HTML page. Just a <script>some_variable_name = {{datastructure|tojson|safe}};<script> section is enough; then access that some_variable_name from your static Javascript code to do interesting things on the page. JSON is a (almost entirely a) subset of Javascript, and the way the tojson filter works is guaranteed to produce a Javascript-compatible data structure for you. The browser will load it just like any other embedded Javascript code.
Sign up to request clarification or add additional context in comments.

1 Comment

This worked great. Thank you very much for the explanation. I'm new to javascript so it didn't dawn on me that's what was happening.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.