I am using flask to build online app. I am grabbing user input using d3.js then send it off to app.py which will use this input to make an api call and grab appropriate data then it will return jsonfied data back to javascript for rendering plot in correct html tag however it keeps on giving me error: Error: DOM element provided is null or undefined

app.py:

import os
from flask import Flask, render_template, jsonify, request, redirect, url_for
from alpha_vantage.timeseries import TimeSeries
import plotly
# import plotly.plotly as py
# import plotly.graph_objs as go


app = Flask(__name__)

api_key = "ssdqwjhwq"

# This will run upon entrance
@app.route("/")
def home():
    return render_template("index.html")

@app.route("/stockchart/<label>")
def stock_data(label):
    ts = TimeSeries(key=api_key, output_format='pandas')
    df, meta_deta = ts.get_daily(label, outputsize="full")
    df.columns = ["open", "high", "low", "close", "volume"]
    data = [{"dates":list(df.index.values)},
            {"close": list(df.close)}]
    return jsonify(data)

if __name__ == "__main__":
    app.run()

my html code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Stock Screener</title>
    <!-- Importing all cdn -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
    <div class="text-center">
        <h2>Stock Screener</h2>
        <h5>Interactive chart with predictions using machine learning</h5>
    </div>

    <div>
        <!-- Input for stock label -->
        <form>
            <label for="stockInput">Enter stock label</label>

            <!-- use js to store input into a variable. -->
            <input type="text" id="stockInput" name="stock_label" placeholder="Label">

            <!-- submit button-->
            <input type="submit" value="submit" id="stocklabelsubmit">
        </form>
    </div>
    <div class="chart">
    </div>

</body>
<script src="../static/js/index.js"></script>
</html>

And my javascript

// give reference to submit button
// Upon click, submitted function will run

d3.select("#stocklabelsubmit").on("click", submitted);

function submitted(){
    d3.event.preventDefault();

    // grab label inputted.
    var inputted_label = d3.select("#stockInput").node().value;
    // refresh input box
    d3.select("#stockInput").node().value = "";
    // pass inputted_label to plot function
    Plot(inputted_label);
};

function Plot(input){
    var url = `/stockchart/${input}`
    // when this function is called call /stock_data function!!
    // data is what is returned from python
    d3.json(url).then(function(data){
        console.log(data);
        console.log(data[0]);
        console.log(data[0].dates);
        var trace = {
            x:data[0].dates,
            y:data[1].close,
            type: "scatter"
        };

        var layout {
            title:"Stock chart",
            xaxis:{
                title:"dates"
            },
            yaxis:{
                title:"closing price"
            }
        };
        var data = [trace];
        // var loc_plot = document.getElementById("chart");

        Plotly.newPlot("chart", data, layout);
    });
};

Error tells me that there is an error in js line 33 = Plotly.newPlot("chart", data,layout); I am not sure how I can fix this everything seems to work fine until plotting as it console logs properly. Any help? Thanks!

1 Answers

0
AndroidNoobie On

According to the documentation, the graphDiv argument of Plotly.newPlot() refers to either a DOM node or string ID of a DOM node.

In your code above, it looks like you are providing neither. You are providing the class of a DOM node, but not an actual DOM node or ID of a DOM node. This probably explains the error you're getting regarding the null or undefined DOM node.

Try changing <div class="chart"> to <div class="chart" id="chart"> (or some other ID), or get the node using Element.querySelector() and pass that in for the DOM node instead and see if that works.