Unable to apply custom pipe to high chart tooltip

2019-07-12 18:33发布

I am trying to implement the tooltip for whisker bloxplotchart highchart in my angular4 application.

I am trying to apply the custom pipe that i have written but it doesnt seem to apply here in highcharts. Is there a different way of doing it in high charts. My custom pipe basically converts numbers that are in thousands to 100K for example and millions to 100M etc. I have shared my code for the custom pipe as well as highchart component

I am trying this in my tooltip but it doesnt seem to apply.. The value is coming blank {point.high |ShortNumberFormat}

Not sure what i am doing wrong ? Please find my code below.

import { Component, Input } from '@angular/core';
import { ShortNumberFormatPipe } from '@wtw/toolkit';
@Component({
    selector: 'app-box-plot-chart',
    template: '<chart [options]="options" (load)="getInstance($event.context)"></chart>',
    styles: [`
        chart{
              display: block;
              width: 100% !important;
              padding:0;
        }
    `]
})
export class BoxPlotChartComponent {
    private _x = new ShortNumberFormatPipe();

    public options: any;
    chart: any;

    @Input() public series: any;
    @Input() public moduleName: string = '';

    constructor() {

        this.options = {

            chart: {
                type: 'boxplot'
            },
            title: {
                text: ''
            },
            legend: {
                enabled: false
            },
            credits: {
                enabled: false
            },
            yAxis: {
                title: {
                    text: ''
                }, plotLines: false
            },
            tooltip: {
                shared: true,
                useHTML: true,
                headerFormat: '<strong style="font-size:12px;color:{point.color}">{point.key}</strong><br><br><table>',
                pointFormat: '<tr><td  style="font-size:10px;">Maximum: </td>' +
                                 '<td style="font-size:10px;"><b>{point.high |shortNumberFormat}</b></td></tr>' +
                              '<tr><td style="font-size:10px;">Upper quartile: </td>' +
                                 '<td style="font-size:10px;"><b>{point.q1} </b></td></tr>' +
                               '<tr><td style="font-size:10px;">Median: </td>' +
                                 '<td style="font-size:10px;"><b>{point.median} </b></td></tr>' +
                                '<tr><td style="font-size:10px;">Lower quartile: </td>' +
                                 '<td style="font-size:10px;"><b>{point.q3}   </b></td></tr>' +
                                 '<tr><td style="font-size:10px;">Minimum: </td>' +
                                 '<td style="font-size:10px;"><b>{point.low} </b></td></tr>' ,
                footerFormat: '</table>',
                valueDecimals: 0
            },
            series: []
        };
    }

    getInstance(chartInstance): void {
        this.chart = chartInstance;
        if(this.moduleName == 'npv'){
            this.options.tooltip.valueDecimals = 0;
        }

        this.redraw();
    }


    ngOnChanges(data: any) {
        if (!data.series.currentValue || !this.chart) return;
        data.series.currentValue.map(s => {
            this.chart.addSeries(s);
        });
        this.chart.reflow();
    }

    redraw() {
        if (!this.chart) return;
        this.chart.addSeries(this.series);


    }

}

Custom pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'shortNumberFormat'
})
export class ShortNumberFormatPipe implements PipeTransform {

  transform(number: any, decimals = 0) {

    if (number === null) {
      return;
    }

    number = parseFloat(number);

    if (isNaN(number)) {
      return;
    }

    if (isNaN(decimals)) {
      return;
    }

    const signPrefix = number < 0 ? '-' : '';
    number = Math.abs(number);

    if (number <= 999) { // hundreds
      number = number.toFixed(decimals);
    } else if (number >= 1000 && number <= 999999) {  // thousands
      number = (number / 1000).toFixed(decimals) + 'K';
    } else if (number >= 1000000 && number <= 999999999) { // millions
      number = (number / 1000000).toFixed(decimals) + 'M';
    } else { // billions
      number = (number / 1000000000).toFixed(decimals) + 'B';
    }

    return signPrefix + number;
  }
}

After failed attempts of transforming the values via graph, I tried it at the component level but unfortunately the component doesnt understand string so it doesnt render the graph. If i comment the assignment it renders correctly.

this.results = this._npvResults.map((result: any) => {
      result.chartSeries.data.forEach(s => {
        s.high = this.shortNumberFormatPipe.transform(s.high,0),
        s.low = this.shortNumberFormatPipe.transform(s.low,0),
        s.median = this.shortNumberFormatPipe.transform(s.median,0),
        s.q1 = this.shortNumberFormatPipe.transform(s.low),
        s.q3 = this.shortNumberFormatPipe.transform(s.q3)

      });
      return createNpvAnalysisResult(result);
    });

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-07-12 18:49

Did you declare your pipe in a module?

 import { FileSizePipe } from './filesize.pipe';

 @NgModule({
 declarations: [
 //...
    FileSizePipe ,
 ],
})

export class AppModule {}

https://toddmotto.com/angular-pipes-custom-pipes

查看更多
我只想做你的唯一
3楼-- · 2019-07-12 19:09

You have this

pointFormat: '<tr><td  style="font-size:10px;">Maximum: </td>' +
                             '<td style="font-size:10px;"><b>{point.high |shortNumberFormat}</b></td></tr>' +
                          '<tr><td style="font-size:10px;">Upper quartile: </td>' +
                             '<td style="font-size:10px;"><b>{point.q1} </b></td></tr>' +
                           '<tr><td style="font-size:10px;">Median: </td>' +
                             '<td style="font-size:10px;"><b>{point.median} </b></td></tr>' +
                            '<tr><td style="font-size:10px;">Lower quartile: </td>' +
                             '<td style="font-size:10px;"><b>{point.q3}   </b></td></tr>' +
                             '<tr><td style="font-size:10px;">Minimum: </td>' +
                             '<td style="font-size:10px;"><b>{point.low} </b></td></tr>' ,

Particulary this point :

<td style="font-size:10px;"><b>{point.high |shortNumberFormat}</b></td></tr>

This bunch of code is the chart code, not Angular code.

You write your Angular code in Typescript. Here, you just write some code that will be processed (or not, I don't really know the library, but let's say it is processed) by the library.

Angular, on the other side, compiles your code as vanilla Javascript.

This means that once your applicatoin is built (or served), you can't update the Angular code anymore.

In this case, that is what you are trying to do. You try to give Angular code to your chart.

You can't do that, it won't work.

If you want to make it work, give it a raw number, like this.

'<td style="font-size:10px;"><b>' + new ShortNumberFormatPipe().transform(point.high) + '</b></td></tr>' +
查看更多
登录 后发表回答