angular-cli: 'this' resolves to a child component instead of the main component

荒凉一梦 提交于 2020-02-06 07:43:36

问题


I am trying to implement this chart component https://www.highcharts.com/stock/demo/candlestick-and-volume in my angular-cli app. The chart is getting its data from a webapi. It allows you to specify a new date range. When you do that an event is being triggered and in that event you can call your webapi service and requst new data.

You configure the chart by passing in some options in the contructor

this.chart = new StockChart(this.chartOptions);

One of the options you can set is an event that gets fired when you select a new date range

this.chartOptions = {
...
xAxis: {
        events: {
          afterSetExtremes: this.afterSetExtremes
        },
        minRange: 3600 * 1000 // one hour
      },
...
}

So when you select a new date range, this function is being called

    afterSetExtremes(e: { min: number; max: number }) {
    console.log('Here we should load data. min: ' + e.min + ' max: ' + e.max);

  }

It is in that function my troubles are because 'this' resolves to the chart control and not my component so I cannot not access my WebApi Service, httpclient or other methods, property in my component.

If I inside the afterSetExtremes function do a

console.log(this);

i get the chart and not the component as I would have expected

if i console.log(this) from my constructor i get the expected value, my component and access to my api service

constructor(private apiService: ApiService, private activateRoute: ActivatedRoute) {
    ... 
    console.log(this);
  }

**All this results in that I cannot call my service and get the updated data as I am unable to reference my apiservice and/or my getChartData function **

Here are the complete code for my component

import { Component, OnInit } from '@angular/core';
import { StockChart } from 'angular-highcharts';
import { ApiService } from '@app/services/snakeApi/api.service';
import { ActivatedRoute } from '@angular/router';
import { finalize } from 'rxjs/operators';
import { ChartDataCandleStick, ChartDataIndicator } from '@app/model/ChartData';
import { Options } from 'highcharts/highstock';

@Component({
  selector: 'app-candlestick-and-volume',
  templateUrl: './candlestick-and-volume.component.html',
  styleUrls: ['./candlestick-and-volume.component.scss']
})
export class CandlestickAndVolumeComponent implements OnInit {
  chart: StockChart;
  chartDataCandleStick: Array<ChartDataCandleStick> = new Array<ChartDataCandleStick>();
  chartDataIndicatorUpper: Array<ChartDataIndicator> = new Array<ChartDataIndicator>();
  chartDataIndicatorLower: Array<ChartDataIndicator> = new Array<ChartDataIndicator>();
  sub: any;
  correlationId: string;
  chartOptions: Options;
  candleStickDataArray: any = [];
  volumeDataArray: any = [];
  indicatorUpperDataArray: any = [];
  indicatorLowerDataArray: any = [];

  constructor(private apiService: ApiService, private activateRoute: ActivatedRoute) {
    this.sub = this.activateRoute.params.subscribe(params => {
      this.correlationId = params.correlationId;

      this.getChartData(-1, -1);

      console.log(this);

    });
  }

  getChartData(min: number, max: number) {
    this.apiService
      .getChartData({ correlationId: this.correlationId, startdateAsUnixTimeStamp: min, enddateAsUnixTimeStamp: max })
      .pipe(
        finalize(() => {
          if (this.chartDataCandleStick.length > 0) {
            this.updateChart();
          }
        })
      )
      .subscribe(response => {
        this.chartDataCandleStick = response.ChartDataCandleStick;
        this.chartDataIndicatorUpper = response.ChartDataIndicatorUpper;
        this.chartDataIndicatorLower = response.ChartDataIndicatorLower;
      });
  }

  updateChart() {
    const candleStickDataLength = this.chartDataCandleStick.length;
    const indicatorUpperDataLength = this.chartDataIndicatorUpper.length;
    const indicatorLowerDataLength = this.chartDataIndicatorLower.length;

    // set the allowed units for data grouping
    let groupingUnits = [],
      i = 0;

    for (i; i < candleStickDataLength; i += 1) {
      this.candleStickDataArray.push([
        this.chartDataCandleStick[i].Date, // the date
        this.chartDataCandleStick[i].Open, // open
        this.chartDataCandleStick[i].High, // high
        this.chartDataCandleStick[i].Low, // low
        this.chartDataCandleStick[i].Close // close
      ]);

      this.volumeDataArray.push([
        this.chartDataCandleStick[i].Date, // the date
        this.chartDataCandleStick[i].Volume // the volume
      ]);
    }

    for (i; i < indicatorUpperDataLength; i += 1) {
      this.indicatorUpperDataArray.push([
        this.chartDataIndicatorUpper[i].Date, // the date
        this.chartDataIndicatorUpper[i].Indicator //  the upper indicator
      ]);
    }

    for (i; i < indicatorLowerDataLength; i += 1) {
      this.indicatorLowerDataArray.push([
        this.chartDataIndicatorLower[i].Date, // the date
        this.chartDataIndicatorLower[i].Indicator //  the lower indicator
      ]);
    }

    // Add a null value for the end date
    if (candleStickDataLength > 0) {
      var endDateChartCandleStick = this.chartDataCandleStick[candleStickDataLength - 1].Date;
      this.chartDataCandleStick = [].concat(this.chartDataCandleStick, [
        [endDateChartCandleStick, null, null, null, null]
      ]);
    }

    if (indicatorUpperDataLength > 0) {
      var endDateChartIndicatorUpper = this.chartDataIndicatorUpper[indicatorUpperDataLength - 1].Date;
      this.chartDataIndicatorUpper = [].concat(this.chartDataIndicatorUpper, [
        [endDateChartIndicatorUpper, null, null, null, null]
      ]);
    }

    if (indicatorLowerDataLength > 0) {
      var endDateChartIndicatorLower = this.chartDataIndicatorLower[indicatorLowerDataLength - 1].Date;
      this.chartDataIndicatorLower = [].concat(this.chartDataIndicatorLower, [
        [endDateChartIndicatorLower, null, null, null, null]
      ]);
    }

    if (!this.chart) {
      this.chart = new StockChart(this.chartOptions);
    }
  }

  afterSetExtremes(e: { min: number; max: number }) {
    console.log('Here we should load data. min: ' + e.min + ' max: ' + e.max);
    // this.getChartData(e.min, e.max);



  }

  ngOnInit() {
    this.chartOptions = {
      rangeSelector: {
        buttons: [
          {
            type: 'hour',
            count: 1,
            text: '1h'
          },
          {
            type: 'day',
            count: 1,
            text: '1d'
          },
          {
            type: 'week',
            count: 1,
            text: '1w'
          },
          {
            type: 'month',
            count: 1,
            text: '1m'
          },
          {
            type: 'year',
            count: 1,
            text: '1y'
          },
          {
            type: 'all',
            text: 'All'
          }
        ],
        inputEnabled: false, // it supports only days
        selected: 0 // all
      },
      title: {
        text: 'AAPL Historical'
      },

      navigator: {
        adaptToUpdatedData: false,
        series: {
          data: this.chartDataCandleStick
        }
      },

      scrollbar: {
        liveRedraw: false
      },

      xAxis: {
        events: {
          afterSetExtremes: this.afterSetExtremes
        },
        minRange: 3600 * 1000 // one hour
      },

      yAxis: [
        {
          labels: {
            align: 'right',
            x: -3
          },
          title: {
            text: 'OHLC'
          },
          height: '80%',
          lineWidth: 1,
          resize: {
            enabled: true
          }
        },
        {
          labels: {
            align: 'right',
            x: -3
          },
          title: {
            text: 'Volume'
          },
          top: '90%',
          height: '10%',
          offset: 0,
          lineWidth: 1
        }
      ],

      series: [
        {
          type: 'candlestick',
          zoomType: 'x',
          name: 'AAPL',
          id: 'aapl',
          data: this.candleStickDataArray,
          dataGrouping: {
            enabled: false
          }
        },
        {
          type: 'column',
          zoomType: 'x',
          name: 'Volume',
          data: this.volumeDataArray,
          yAxis: 1,
          dataGrouping: {
            enabled: false
          }
        },
        {
          type: 'spline',
          zoomType: 'x',
          name: 'indicatorUpper',
          id: 'indicatorUpper',
          data: this.indicatorUpperDataArray,
          dataGrouping: {
            enabled: false
          }
        },
        {
          type: 'spline',
          zoomType: 'x',
          name: 'indicatorLower',
          id: 'indicatorLower',
          data: this.indicatorLowerDataArray,
          dataGrouping: {
            enabled: false
          }
        },
        {
          type: 'flags',
          name: 'Flags on series',
          data: [
            {
              x: 946980000000,
              title: 'Buy',
              text: 'Some event with a description'
            },
            {
              x: 946980060000,
              title: 'Sell',
              text: 'Some event with a description'
            },
            {
              x: 946980060001,
              title: 'Short',
              text: 'Some event with a description'
            },
            {
              x: 946980120000,
              title: 'Buy',
              text: 'Some event with a description'
            },
            {
              x: 946980120001,
              title: 'Buy',
              text: 'Some event with a description'
            },
            {
              x: 946980180000,
              title: 'Sell',
              text: 'Some event with a description'
            },
            {
              x: 946980180001,
              title: 'Short',
              text: 'Some event with a description'
            },
            {
              x: 946980240000,
              title: 'Buy',
              text: 'Some event with a description'
            },
            {
              x: 946980240001,
              title: 'Buy',
              text: 'Some event with a description'
            }
          ],
          onSeries: 'dataseries',
          shape: 'squarepin'
        }
      ]
    };
  }
}


回答1:


I come from freelancer and I have looked at your code and if I was in your in your shoes I would try a few things first, the first of which is to hard bind the function like so:

afterSetExtremes: this.afterSetExtremes.bind(this)

or add a reference to it like so

const afterSetExtremes = this.afterSetExtremes;

and then reference it in your config object.



来源:https://stackoverflow.com/questions/59806505/angular-cli-this-resolves-to-a-child-component-instead-of-the-main-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!