pass JavaScript var back to Flask and have ajax reload

Preface: I’ve already looked at similar questions and tried to extrapolate code/concepts to help resolve with no luck.

-https://stackoverflow.com/questions/43645790/passing-javascript-variable-to-python-flask

-https://stackoverflow.com/questions/10313001/is-it-possible-to-make-post-request-in-flask

Please do not just close because it’s a "similar" question.

I’m designing a simple flask app which can be viewed live here:

https://flaskapp.gullp.repl.co/

enter image description here

There is a chart using chart.js and underneath resides a Pandas dataframe.

Goal: When you click a bar on the chart, it filters the dataframe. Concretely, if I click the "Big Home" bar, the dataframe below will only show values where the label = "Big Home".

Attempts:

Trying to use Ajax/jQuery to pass the value back to Python and have it filter the dataframe accordingly.

I’ve been able to get the corresponding clicked value (i.e when you click the first bar it will output "big home") My thought is that i can take this value, pass it back to python, and have it filter the dataframe, and subsequently reload the dataframe using ajax on the site.

Current attempt = bar is clicked -> corresponding value is saved to javascript var -> the javascript var is loaded into json string -> json string is then loaded back to flask -> flask rerenders dataframe.

@app.route("/", methods=["GET", "POST"])
def home():
    labels = chart_df['label'].tolist()
    values = chart_df['value'].tolist()
    return render_template('index.html', values=values, labels=labels, column_names=df.columns.values, row_data=list(df.values.tolist()), zip=zip)

    if request.method == "POST":
        data = request.get_json()
        return jsonify(status="success", score=data)
        
    else:
        return render_template('index.html', score='', values=values, labels=labels, column_names=df.columns.values, row_data=list(df.values.tolist()), zip=zip)

the onclick logic i’m using to grab value from graph and pass it to variable:

             //below allows you to click the chart and get the respective value. you will pass this value to python
                ,onClick: function(c,i) {
      
                e = i[0];
                //console.log(e._index)
                var x_value = this.data.labels[e._index];
                var y_value = this.data.datasets[0].data[e._index];
               // console.log(x_value);
                //console.log(y_value);
                console.log('you clicked the graph, now the x value is = ' + x_value)
        
              } 
          }
      });

//below puts the clicked value into a json format so we can pass it back to python/flask to reload the dataframe table that resides below the chart/graph. I'm attempting to pass it via ajax.

//start off with default chart values
      var x_value = '444'
      console.log('when the page loaded we defaulted x-value = ' + x_value + ' now try clicking one of the bars below.')
      var ctx = document.getElementById('myChart').getContext('2d');



    var chart_clicked_data = { 'score' : x_value}
      console.log('this is the json chart clicked data that we want to pass back to flask = ' + JSON.stringify(chart_clicked_data) )

the ajax im attempting to implement

     $.ajax({
    type: "POST",
    url: "/",
    contentType: "application/json",
    data: JSON.stringify(chart_clicked_data),
    dataType: "json",
    success: function(response) {
        console.log(response);
    },
    error: function(err) {
        console.log(err);
    }
});

Problem:

I just learned flask, javascript, & jquery this week, so go easy on me, but I’m unable to get the entire process to work.

enter image description here

I’m suspecting that i have no way to trigger the post method? Not sure how to accomplish this.

My entire code is running here (can be edited here too) -> https://repl.it/join/rbkobiqi-gullp

app.py (application factory)

import os
import random
import pandas as pd
import datetime as dt
from flask import Flask, render_template, url_for, request, jsonify


'''dataframe for table/graph'''
df = pd.DataFrame({'label': ['Big Home','Big Home', 'Big Home',  'Medium Home', 'Medium Home', 'Small Home'], 
                   'value': [10, 9, 9, 7, 6, 2]})

'''dataframe to display graph'''
chart_df = df.copy()
chart_df = chart_df.groupby("label").count().reset_index()



'''Application Factory'''
app = Flask(  # Create a flask app
    __name__,
    template_folder='templates',  # Name of html file folder
    static_folder='static'  # Name of directory for static files
)

@app.route("/", methods=["GET", "POST"])
def home():
    labels = chart_df['label'].tolist()
    values = chart_df['value'].tolist()
    return render_template('index.html', values=values, labels=labels, column_names=df.columns.values, row_data=list(df.values.tolist()), zip=zip)

    if request.method == "POST":
        data = request.get_json()
        return jsonify(status="success", score=data)
        
    else:
        return render_template('index.html', score='', values=values, labels=labels, column_names=df.columns.values, row_data=list(df.values.tolist()), zip=zip)



@app.route('/tabletest')
def hello_world():
    return chart_df.to_html(header="true", table_id="table")


if __name__ == "__main__":  # Makes sure this is the main process
    app.run( # Starts the site
        host='0.0.0.0',  # EStablishes the host, required for repl to detect the site
        port=random.randint(2000, 9000),  # Randomly select the port the machine hosts on.
    debug=True
    )

index.html (under templates)

 <!doctype html>
 <html>
   <head>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
   </head>
  <body>

 <center><canvas id="myChart" width="600" height="200"></canvas>

    <script>
       var ctx = document.getElementById('myChart').getContext('2d');
       Chart.defaults.global.responsive = false;


      var myChart = new Chart(ctx, {
          type: 'bar',
          data: {
              labels: /* {{ labels }}*/ ['Big Home', 'Medium Home', 'Small Home'] ,
              datasets: [{
                  label: 'count per label',
                  data: /*{{ values }} */ [3,2,1]
              }]
          },
          options: {
              scales: {
                  yAxes: [{
                      ticks: {
                          beginAtZero: true
                      }
                  }]
              }
              //below allows you to click the chart and get the respective value. you will pass this value to python
                ,onClick: function(c,i) {
      
                e = i[0];
                //console.log(e._index)
                var x_value = this.data.labels[e._index];
                var y_value = this.data.datasets[0].data[e._index];
               // console.log(x_value);
                //console.log(y_value);
                console.log('you clicked the graph, now the x value is = ' + x_value)
        
              } 
          }
      });

//below puts the clicked value into a json format so we can pass it back to python/flask to reload the dataframe table that resides below the chart/graph. I'm attempting to pass it via ajax.

//start off with default chart values
      var x_value = '444'
      console.log('when the page loaded we defaulted x-value = ' + x_value + ' now try clicking one of the bars below.')
      var ctx = document.getElementById('myChart').getContext('2d');



    var chart_clicked_data = { 'score' : x_value}
      console.log('this is the json chart clicked data that we want to pass back to flask = ' + JSON.stringify(chart_clicked_data) )

      $.ajax({
    type: "POST",
    url: "/",
    contentType: "application/json",
    data: JSON.stringify(chart_clicked_data),
    dataType: "json",
    success: function(response) {
        console.log(response);
    },
    error: function(err) {
        console.log(err);
    }
});





      </script>


<!-- Table Logic Below -->

<br>
<br>
     <div> Your current score selected is = {{score}} </div>
<br>
<br>
Trying to make it so when you click "Big Home" for example, the data table will only show values for "big home"
<br>
<br>
      <table border='1'>
        <thead>

          <tr>
            {% for col in column_names %}
            <th>
            
              {{col}}
             
            </th>
            {% endfor %}
          </tr>

        </thead>
        <tbody>
          {% for row in row_data %}
          <tr>
            {% for col, row_ in zip(column_names, row) %}
            <td>{{row_}}</td>
            {% endfor %}
          </tr>
          {% endfor %}

         
        </tbody>
  
      </table>

</center>

</body>
</html>


72 thoughts on “pass JavaScript var back to Flask and have ajax reload”

  1. certainly like your web-site but you need to check the spelling on several of your posts. A number of them are rife with spelling issues and I in finding it very troublesome to inform the reality on the other hand I’ll surely come again again.

    Reply
  2. Hi, Neat post. There’s an issue with your website in internet explorer, could test thisK IE still is the marketplace leader and a huge element of other folks will miss your fantastic writing because of this problem.

    Reply

Leave a Comment