0

I have this in templates/index.html`:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <style>

    </style>
</head>
<body>
    <div id="graphDiv"></div>

    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="{{ url_for('static', filename='main.js') }}"></script>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <script>

    </script>
</body>
</html>

and I have this in app.py:

import json

from flask import Flask, render_template
import pandas as pd

app = Flask(__name__)

@app.route("/")

def index():
    df = pd.read_csv('data.csv').drop('Open', axis=1)
    chart_data = df.to_dict(orient='records')
    chart_data = json.dumps(chart_data, indent=2)
    data = {'chart_data': chart_data}
    return render_template("index.html", data=data)


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port =5000)

and I didn't want to put the javascript inline in index.html but instead created a directory called static/ and put there the style.css and main.js and it contains this code:

var graphData = {{ data.chart_data | safe }}

var margin = {top: 30, right: 50, bottom: 30, left: 50};
var svgWidth = 600;
var svgHeight = 270;
var graphWidth = svgWidth - margin.left - margin.right;
var graphHeight = svgHeight - margin.top - margin.bottom;

var parseDate = d3.time.format("%Y-%m-%d").parse;

var x = d3.time.scale().range([0, graphWidth]);
var y = d3.scale.linear().range([graphHeight, 0]);

var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(5);

var highLine = d3.svg.line()
    .x(function(d) { return x(d.Date); })
    .y(function(d) { return y(d.High); });

var closeLine = d3.svg.line()
    .x(function(d) { return x(d.Date); })
    .y(function(d) { return y(d.Close); });
var lowLine = d3.svg.line()
    .x(function(d) { return x(d.Date); })
    .y(function(d) { return y(d.Low); });

var area = d3.svg.area()
    .x(function(d) { return x(d.Date); })
    .y0(function(d) { return y(d.Low); })
    .y1(function(d) { return y(d.High); })

var svg = d3.select("#graphDiv")
    .append("svg")
        .attr("width", svgWidth)
        .attr("height", svgHeight)
    .append("g")
        .attr("transform", 
        "translate(" + margin.left + "," + margin.top + ")")

function drawGraph(data) {
    // For each row in the data, parse the date
    // and use + to make sure data is numerical
    data.forEach(function(d) {
        d.Date = parseDate(d.Date);
        d.High = +d.High;
        d.Close = +d.Close;
      d.Low = +d.Low;
            });
    // Scale the range of the data
        x.domain(d3.extent(data, function(d) { return d.Date; }));
        y.domain([d3.min(data, function(d) {
            return Math.min(d.High, d.Close, d.Low) }),
            d3.max(data, function(d) {
            return Math.max(d.High, d.Close, d.Low) })]);
    // Add the area path
        svg.append("path")
            .datum(data)
            .attr("class", "area")
            .attr("d", area)
    // Add the highLine as a green line
        svg.append("path")
            .style("stroke", "green")
            .style("fill", "none")
            .attr("class", "line")
            .attr("d", highLine(data));
    // Add the closeLine as a blue dashed line
        svg.append("path")
            .style("stroke", "blue")
            .style("fill", "none")
            .style("stroke-dasharray", ("3, 3"))
            .attr("d", closeLine(data));
    // Add the lowLine as a red dashed line
        svg.append("path")
            .style("stroke", "red")
            .attr("d", lowLine(data));
    // Add the X Axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + graphHeight + ")")
            .call(xAxis);
    // Add the Y Axis
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);
    // Add the text for the "High" line
        svg.append("text")
            .attr("transform", "translate("+(graphWidth+3)+","+y(graphData[0].High)+")")
            .attr("dy", ".35em")
            .attr("text-anchor", "start")
            .style("fill", "green")
            .text("High");
    // Add the text for the "Low" line
        svg.append("text")
            .attr("transform", "translate("+(graphWidth+3)+","+y(graphData[0].Low)+")")
            .attr("dy", ".35em")
            .attr("text-anchor", "start")
            .style("fill", "red")
            .text("Low");
    // Add the text for the "Close" line
        svg.append("text")
            .attr("transform", "translate("+(graphWidth+3)+","+y(graphData[0].Close)+")")
            .attr("dy", ".35em")
            .attr("text-anchor", "start")
            .style("fill", "blue")
            .text("Close");
};

drawGraph(graphData);

when I ran the flask server I get this error: SyntaxError: expected property name, got '{' in the first line of the js code var graphData = {{ data.chart_data | safe }}. Now if I put this javascript code inline in index.html everything works fine. I did some research but nothing fixed my issue and I still don't know why is this happening.

2
  • Its happening because thats not valid JavaScript syntax. Thats Jinja2 templating syntax. You'll just need to include that one line in your template and then include the other javascript file afterwards and it will be fine. Commented Nov 27, 2019 at 16:10
  • @Craicerjack thanks, I have tried that but then I get graphData is not defined Commented Nov 27, 2019 at 16:11

1 Answer 1

2
<!DOCTYPE html>
<html lang="en">
<head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <style>

    </style>
</head>
<body>
    <div id="graphDiv"></div>

    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript">
      var graphData = {{ data.chart_data | safe }}
    </script>
    <script type="text/javascript" src="{{ url_for('static', filename='main.js') }}"></script>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</body>
</html>  

Its happening because thats not valid JavaScript syntax. Thats Jinja2 templating syntax.

You need to define graphData before you can use it in your main.js file.

Sign up to request clarification or add additional context in comments.

2 Comments

I see, I should have put var graphData = {{ data.chart_data | safe }} before main.js . Thanks a lot!
Happy to help. Glad you have it sorted

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.