Search code examples
extwebcomponents

How could I render a ExtWebComponent Area Chart using Alpha Vantage stock data?


I would like to use Alpha Vanatage stock data in my ExtWebComponent chart. How could I fetch the data and render it in a Cartesian Area chart?


Solution

  • If you've generated an ExtWebComponents project, you could add these 2 files and declare the web component html element tag.

    This is how it could look

    Usage

    In the html file like index.html declare my-chart-area which is defined in the web component below.

    AreaChartComponent.html - HTML Template

    <ext-cartesian 
      width="1000px"
      height="600px"
      downloadServerUrl="http://svg.sencha.io" 
      shadow="true"
      insetPadding="25 35 0 10"
      axes='[{
              "type": "numeric" ,
              "position": "left" ,
              "fields": [ "1. open" ],
              "label": { "rotate": { "degrees": "-30" } },
              "grid": { "odd": { "fill": "#e8e8e8" } },
              "title": { "text": "Alphabet Inc Stock Data" , "fontSize": "20" }
          },
          {
              "type": "category",
              "position": "bottom",
              "fields": "time",
              "grid": "true",
              "title": { "text": "Monthly", "fontSize": "20" }
        }]'
        legend='{
          "type": "sprite",
          "position": "bottom"
        }'
        series='[{
          "type": "area" ,
          "xField": "time",
          "yField": [ "1. open", "2. high", "3. low", "4. close" ],
          "title": [ "open", "high", "low", "close" ],
          "style": { "stroke": "black" , "lineWidth": "2", "fillOpacity": "0.8" },
          "colors": ["#003f5c", "#58508d", "#bc5090", "#ff6361", "#ffa600"]
        }]' 
        platformConfig='{
          "phone": { "insetPadding": "15 5 0 0" }
        }'>
    </ext-cartesian>
    

    AreaChartComponent.js - Web Component

    import template from './AreaChartComponent.html'
    
    Ext.require([
      'Ext.chart.theme.Midnight',
      'Ext.chart.theme.Green',
      'Ext.chart.theme.Muted',
      'Ext.chart.theme.Purple',
      'Ext.chart.theme.Sky',
      'Ext.chart.series.Area',
      'Ext.chart.axis.Numeric',
      'Ext.chart.axis.Category'
    ]);
    
    class AreaChartComponent extends HTMLElement {
    
      constructor() {
        super()
      }
    
      connectedCallback() {
        this.innerHTML = template;
    
        this._fetchChartData();
      }
    
      disconnectedCallback() {
      }
    
      attributeChangedCallback(attrName, oldVal, newVal) {
      }
    
      /**
       * Fetch the chart data from https://www.alphavantage.co/ using an API Key. 
       * 
       * TODO Fetch your api key here: https://www.alphavantage.co/support/#api-key 
       */
      _fetchChartData() {
        let me = this;
        let apiKey = 'demo'; 
        let stockSymbol = 'GOOGL';
        let url = `https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=${stockSymbol}&apikey=${apiKey}`;
    
        fetch(url)
          .then(response => {
            return response.json();
          })
          .then(json => {
            return me._flattenData(json);
          })
          .then(jsonflatRows => {
            me._renderChart(jsonflatRows);
          })
          .catch(err => {
            console.log("error", err);
          })
      }
    
      /**
       * The goal is to flatten the nested json data, so it's easy to consume in the charts.
       * @param json data
       * @returns {*[]} array of json data
       * @private
       */
      _flattenData(json) {
        console.log("json=", json);
    
        let jsonTimes = json['Monthly Time Series']
    
        let flatRows = [];
    
        for (let jsonTime in jsonTimes) {
          let row = {
            "time": jsonTime
          };
    
          let jsonNestedTime = jsonTimes[jsonTime];
    
          for (let nestedKey in jsonNestedTime) {
            row[nestedKey] = jsonNestedTime[nestedKey];
          }
    
          flatRows.push(row);
        }
    
        return flatRows.reverse();
      }
    
      _renderChart(jsonflatRows) {
        console.log('_renderChart jsonflatRows=', jsonflatRows);
    
        let store = Ext.create('Ext.data.Store', {
          fields: ["time", "1. open", "2. high", "3. low", "4. close", "5. volume"]
        });
        store.loadData(jsonflatRows);
    
        let areaChartEl = this.querySelector('ext-cartesian');
        areaChartEl.ext.bindStore(store);
      }
    
    }
    window.customElements.define('my-chart-area', AreaChartComponent);
    

    Source

    https://gist.github.com/branflake2267/4652a5d7188dfe0b33d3d02a808d8d74