1

After long searching on here and on the web I could not find what I require. Here is a distilled minimum verifiable example of my issue.

To set the background for the problem, here is the actual use case that I intend to implement. There is a heatmap on endpoint /heatmap, users can click on the cells and they should be redirected to a different endpoint /more-info-on-cell. Depending on the cell clicked, the user will get different results. I almost get the intended result. The only issue is that the page is not really properly rendered because the javascript of /more-info-on-cell does not get executed for some reason.

Here is the folder structure that you require for this example:

root
|-templates
|  -index.html
|  -page.html
|-index.py

And here are the files: index.html

  <!DOCTYPE html>
  <html>
  <head> 
  <title>Title of the document</title> 
  </head>

  <body>
      <a id="clickMe" style="cursor: pointer">Click here to send POST to render template on the backend</a>
  </body>

  <script 
    src="https://code.jquery.com/jquery-3.4.1.min.js" 
    integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" 
    crossorigin="anonymous"></script>
  <script>
      $(document).ready(function() {
          $("#clickMe").on('click', function() {
              console.log('clicked, making a request')

              $.ajax({
                  type: 'POST',
                  url: '/',
                  data: JSON.stringify({}),
                  contentType: 'application/json',
                  success: function(response) { window.document.write(response);  }
              })
          })
      })
  </script>

  </html>

page.html

 <!DOCTYPE html>
 <html>
 <head>
 <title>Title of the document</title>
 </head>

 <body>
 The content of the document......
 </body>

 <script
   src="https://code.jquery.com/jquery-3.4.1.min.js"
   integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
   crossorigin="anonymous"></script>
     <script>
         $(document).ready(function() {
             alert('the doc is ready');
         })
     </script>

 </html>

index.py

 #!/usr/bin/env python3
 from flask import Flask, request, render_template, jsonify
 app = Flask(__name__)

 @app.route("/", methods=["GET", "POST"])
 def index():
     if request.method == "GET":
         return render_template('index.html')
     elif request.method == "POST":
         return render_template('page.html')

You can verify that if you click on the link in index.html you are successfully redirected to page.html but its javascript is never executed. And so you never get the alert that we have defined in page.html.

The problem should be solved by completely working with the flask backend here, since the templates in my actual use case have jinja variables in them too. Everything works perfectly if you make a request through a form with method having the correct url and action being POST. Although, as soon as I start making javascript client POST requests, it sort of works in that I get to the right page, but it is rendered incorrectly + javascript on document ready never gets executed.

Naz
  • 1,814
  • 1
  • 14
  • 35
  • I guess one solution, albeit a weird one, would be to store the information of what cell is clicked on in some sort of a hidden input form and once I save it into these hidden inputs, I simulate the click on the submit button of also a hidden form. This should work. – Naz Jul 05 '19 at 10:39
  • like this: https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit – Naz Jul 05 '19 at 11:19

1 Answers1

0

For anyone who has such a use case too, ensure that you use a method post like below (put it inside the index.html in this case):

  <script>
      $(document).ready(function() {
          $("#clickMe").on('click', function() {
              console.log('clicked, making a request')

             post('/', {'key-1': 'val-1'});
          })
      })

 function post(path, params, method='post') {
     const form = document.createElement('form');
     form.method = method;
     form.action = path;

     for (const key in params) {
         if (params.hasOwnProperty(key)) {
             const hiddenField = document.createElement('input');
             hiddenField.type = 'hidden';
             hiddenField.name = key;
             hiddenField.value = params[key];

             form.appendChild(hiddenField);
         }
     }

     document.body.appendChild(form);
     form.submit();
 }
  </script>

This creates a hidden form on the web page and then submits the form, from then onwards, flask processes everything properly.

Naz
  • 1,814
  • 1
  • 14
  • 35