swimlane / ngx-charts

:bar_chart: Declarative Charting Framework for Angular
https://swimlane.github.io/ngx-charts/
MIT License
4.29k stars 1.15k forks source link

wrong context of AxisTickFormatting methods #261

Closed ctaepper closed 5 years ago

ctaepper commented 7 years ago

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here

Current behavior

import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { DatePipe } from '@angular/common';

@Component({
  selector: 'app-value-history',
  template: `
    <ngx-charts-line-chart
      [xAxisTickFormatting]="xAxisTickFormatting"
    </ngx-charts-line-chart>
  `
})
export class ValueHistoryComponent {

   // ...
  constructor(private datePipe: DatePipe) { }

  xAxisTickFormatting(value) {
    return this.datePipe.transform(value, 'short');
  }
}

throws an error:

TypeError: Cannot read property 'transform' of undefined
    at XAxisTicksComponent.webpackJsonp.479.ValueHistoryComponent.xAxisTickFormatting (value-history.component.ts:60)

because the this in the formatting function seems to be the internal xAxisTickComponent

Expected behavior i expect to be able to use the injected datePipe in the AxisTickFormatting function

Reproduction of the problem see example above

What is the motivation / use case for changing the behavior? i want to use angular2 LOCALE_ID to format the date for various countries

Please tell us about your environment: OSX / Webstorm

marjan-georgiev commented 7 years ago

You can change the context like this:

<ngx-charts-line-chart
    [xAxisTickFormatting]="xAxisTickFormatting.bind(this)"
</ngx-charts-line-chart>
eshcharc commented 7 years ago

@marjan-georgiev It seems that, when using the "bind" syntax, it makes the tooltipTemplate not showing anymore. Some kind of a conflict b/w the two. Can you refer to that?

marjan-georgiev commented 7 years ago

@eshcharc what tooltipTemplate are you referring to? Can you provide a plunkr please?

eshcharc commented 7 years ago

@marjan-georgiev tooltipTemplate is a custom template for a tooltip that you set as a content child (look for it in the API). Without xAxisTickFormatting binded to parent component it is visible, but when included, tooltip is not shown. No plunkr, sorry.

summitmman-zz commented 7 years ago

The same issue here. When I use the "bind" syntax, the tootltip which used to appear when we hover on a bar chart bar, displays no more. And i am not using a tooltip template, it was the default tooltip which used to appear previously

https://swimlane.github.io/ngx-charts/#/ngx-charts/bar-vertical just hover on any of the bar from the above link

kitloong commented 6 years ago

Hi,

The following workaround

<ngx-charts-line-chart
    [xAxisTickFormatting]="xAxisTickFormatting.bind(this)"
</ngx-charts-line-chart>

is not working for me. Will this issue reopen and further investigate?

thummelt commented 6 years ago

Tried that workaround too - does not really solve that problem. I noticed that the labels on my xAxis are constantly recreated by the ticksFormatting which could be the reason for the missing tooltip!

tariknz commented 6 years ago

bind(this) is really half of it. Because if you're using a provider in the function, that will be in the wrong context too.

For this specific case what you can do is inside your function, create a new instance of the pipe you are using (i.e. new DatePipe(this.locale)). That seems to work for me.

rutemja commented 6 years ago

I had the same problem. This workaround helped me for now, but I still have these issues:

  1. I get [Angular] Unknown method 'bind' warnings in VS Code (Might be fixed in the future: https://github.com/angular/vscode-ng-language-service/issues/93).
  2. I have a custom line-chart component and it's not possible to use the xAxisTickFormatting/xAxisTickFormatting inputs to write the formatting logic in a parent component. I get a lot of [Violation] 'setTimeout' handler took xx ms warnings in Chrome then.

So I would suggest to open this issue again.

marjan-georgiev commented 6 years ago

@rutemja could you create a stackblitz with what you have please?

rutemja commented 6 years ago

Edit: Now I got it running: https://stackblitz.com/edit/ngx-charts-axistickformatting-running-version

rutemja commented 6 years ago

Also I now got a version, in which my issues are shown: https://stackblitz.com/edit/ngx-charts-axistickformatting-buggy-version

Because there are only a few data-points, the 'setTimeout' is not coming that much. But therefore I have this 'requestAnimationFrame' message more often: image

Also the IDE now shows the Unknown method 'bind' warning: image

tariknz commented 6 years ago

@rutemja you need to do it in your component: public xAxisTickFormattingFn = this.xAxisTickFormatting.bind(this);

Then just use xAxisTickFormattingFn in your template

erichstark commented 6 years ago

I had the same issue with formatting functions. I solved it with this attriubute in template: [xAxisTickFormatting]="xAxisTickFormatting"

and sample method inside .ts file (you have to create your desired implementation)

xAxisTickFormatting(value): string {
    return value.toString();
  }
shmarlya commented 6 years ago

[xAxisTickFormatting]="xFormat" // in your template guys just simple declare function like this:

 xFormat = (e) => {
   // where e - value of tick by default
   // console.log(this);
   // now you have access to your component variables
   return e + this.someVariable
 }
marjan-georgiev commented 5 years ago

@tariknz and @shmarlya's suggestions are correct. Instantiate the function as a variable in your component, and pass it to the input. Binding it in the template will cause it to be rebound on every changedetection cycle.

pauljanns commented 2 years ago

The accepted solution would trigger the xFormat function on every change detection cycle which is more than not ideal.