title: How to generate graphs in real time server side using Chartjs + Nodejs + Express + Consumption of Api?
body: <p>I am building a system with nodejs + express + ejs ... This system is a panel of graphics and for this I chose to use the api of the new Chartjs 2x ...</p>
  
  <p>I know to use the Chartjs api on the client side and usually when I do this I use object-oriented javascript with es6 ...</p>
  
  <p><strong>What is the problem I'm having?</strong></p>
  
  <p>As I'm consuming an api to generate the graphics, I do not know the amount of graphics and much less the information of the same (so far so good), however as I'm trying on nodejs I would like to know the best option for me to generate these dynamic graphs and randomly server-side, directly to the client.</p>
  
  <p><strong>My question is about the generation and insertion of graphics in EJS and mainly the manipulation of certain graphics.</strong></p>
  
  <p><strong>Function Example:</strong></p>
  
  <pre><code>class GraphBar extends Graph {
      constructor(id){
          super(id, 'bar');
      }
  
      /** @description: MANIPULAÇÃO DE DADOS NO GRÁFICO */
      set data(value) { this.value = value; }
      get data(     ) { return this.value;  }
  
      addData(){
          return {
              labels:              super.graphLabels,
              datasets: [{
                  label:           super.graphLabel,
                  data:            super.graphData,
                  backgroundColor: super.graphBgColors,
                  borderColor:     super.graphBorderColors,
                  borderWidth:     1
              }]
          };
      }
  
      addOptions(){
          return {
              legend: {
                  display: false
              },
              scales: {
                  yAxes: [{
                      display: false,
                      ticks: {
                          fontColor: "white",
                          beginAtZero:true
                      },
                      gridLines: {
                          display:    false,
                          drawBorder: false
                      }
                  }],
                  xAxes: [{
                      display: true,
                      ticks: {
                          fontColor: "white",
                          beginAtZero: true,
                          display: false
                      },
                      gridLines: {
                          display:    false,
                          drawBorder: false
                      }
                  }]
              },
          }
      }
  
      //NÚCLEOS DE PLUGINS DA API DO GRÁFICO
      /** @description: APÓS O DESENHO DO DATASETS NO GRÁFICO */
      afterDatasetDraw(){
          return {
              afterDatasetDraw: chartInstance =&gt; this.showValueOnTopBar(chartInstance)
          }
      }
  
      /** @description: ANTES DE RENDERIZAR O GRÁFICO */
      beforeRender(){
          return {
              beforeRender: chartInstance =&gt; this.showBarZeroValue(chartInstance)
          }
      }
  
      //PLUGINS
      /** @description: INSERE OS VALORES EM CIMA DO GRÁFICO */
      showValueOnTopBar(chartInstance){ 
          if(chartInstance !== undefined){
              super.graphChangeFontStyleOnTopGraph(chartInstance, Chart.defaults.global.defaultFontFamily, '15', 'white', 'bold', 'center', 'bottom');
  
              Chart.helpers.each(this.data.datasets.forEach((dataset, indexDataset) =&gt; {
                  Chart.helpers.each(chartInstance.getDatasetMeta(indexDataset).data.forEach((data, indexData) =&gt; {
                      const graphCenterPoint = data.getCenterPoint();
                      chartInstance.ctx.fillText(dataset.data[indexData], graphCenterPoint.x, graphCenterPoint.y);
                  }), this);
              }), this);
          }
      }
  
      /** @description: ALTERA O TAMANHO DAS BARRAS NO GRÁFICO, DE VALORES ENTRE 0 ~ -0.3 */
      showBarZeroValue(chartInstance){
          Chart.helpers.each(this.data.datasets.forEach((datasets, indexDataset) =&gt; {
              Chart.helpers.each(chartInstance.getDatasetMeta(indexDataset).data.forEach((data, indexData) =&gt; {
                  const graphValue = datasets.data[indexData];
  
                  if(graphValue &lt;= 0 &amp;&amp; graphValue &gt;= -0.3) {
                      const graphMeta  = datasets._meta[0];
                      const graphModel = graphMeta.data[indexData]._model;
  
                      (graphValue &gt;= -0.1) ? graphModel.y = (graphModel.base - 10) : graphModel.y = (graphModel.base + 10);
                  }
              }), this);
          }), this);
      }    
  }
  </code></pre>
  
  <p><strong>Controller Example:</strong></p>
  
  <pre><code>module.exports.home = (app, req, res) =&gt; {
      res.render('home/view', {
          data: {
              general: {
                titlePage:           'TELA 1',
                titleNavbar:         'ANALYTICAL PANEL',
                mainIndicatorValue:  '0 m²',
                mainPercentageValue: '-100%',
              }
          },
          check: {
              general: { 
                  hasHomePage:              true, 
                  hasShoppingPage:          false, 
                  hasShopkeeperPage:        false, 
                  hasShopkeeperDetailPage:  false,
                  hasShopkeeperComparePage: false
              },
              api:{ 
                  hasConsuptionApi: false,
                  hasApiError:      false
              }
          }
      });
  }
  
  module.exports.homeConsumeApi = (app, req, res) =&gt; {
      const apiDAO = new app.models.DAO.api(req, res);
            apiDAO.getResponseAxios().then ( response =&gt; {
                res.render('home/view', {
                    data: {
                        general: {
                            titlePage: 'TELA 1',
                            titleNavbar: 'ANALYTICAL PANEL'
                        },
                        api: { apiResponse: response.data }
                    },
                    check: {
                        general: {
                            hasHomePage:              true,
                            hasShoppingPage:          false,
                            hasShopkeeperPage:        false,
                            hasShopkeeperDetailPage:  false,
                            hasShopkeeperComparePage: false
                        },
                        api: {
                            hasConsuptionApi: true,
                            hasApiError:      false
                        }
                    }
                  });
              }).catch (error =&gt; {
                  res.render('home/view', {
                      data: {
                          general: { 
                              titlePage:   'TELA 1', 
                              titleNavbar: 'ANALYTICAL PANEL' 
                          },
                          apiErrorMsg: { 
                              Status:     error.response.status, 
                              StatusText: error.response.statusText 
                          }
                      },
                      check: {
                          general: {
                              hasHomePage:              true,
                              hasShoppingPage:          false,
                              hasShopkeeperPage:        false,
                              hasShopkeeperDetailPage:  false,
                              hasShopkeeperComparePage: false
                          },
                          api: {
                              hasConsuptionApi: true,
                              hasApiError:      true
                          }
                      }
                    });
              });    
  }
  </code></pre>