3

I am locally using following highcharts dependencies:

  • "angular-highcharts": "5.2.12"
  • "highcharts": "6.1.0"
  • "@types/highcharts": "5.0.19"

Here is a live demo of of my source code,

First of all I would like to point out that the usage and enabling of the noData functionality for highCharts is quite shady. There is no proper guideline available any where regarding how to use it properly.

Now coming on to the issue, few days back I realized the need to show a proper "no data available" message instead of showing empty charts. I did some research and found that it can be enabled in highcharts and found a working demo of it in plain JavaScript. So now how can we use it with Angular 5? That required some more R&D and finally I figured it out,

import * as noDataToDisplay from 'highcharts/modules/no-data-to-display.src';
...    
@NgModule({
  ...
  providers: [
  { provide: HIGHCHARTS_MODULES, useFactory: () => [noDataToDisplay] }
]

(note: ^^ this approach is not working on the linked stackBlits demo, not sure why! )

I did succeeded in enabling it locally in my repo using the above way, but its not robust, i.e. it does not appears consistently.

Next I wanted to toggle noData message dynamically, i.e update it programmatically so I am tried the following approach:

const options = this.chartConfig.ref.options;
  options.lang.noData = `no data from: ${chartData.customMsgFromDate} to ${chartData.customMsgEndDate}.`;
this.chartConfig.ref.update(options, true);

This did worked once when you toggle the visibility of the series from the legend box, but again this also doesn't seems to be working now though. I have following questions,

  1. What is the proper way of using noData option with angular 5
  2. How to make sure it appears consistently? probably different configuration like setData([]) or setData(null) makes it appears in consistently, but I am not able to find out one root cause behind its inconsistency.
  3. How can I toggle noData message dynamically.

Also if there is anything I can improve do let me know, thanks in advance.

P.S I did manage to find this fiddle regarding achieving things using plain JavaScript but haven't been able to achieve anything using angular highcharts. Here is the code attached fiddle seems to be using.

if (!chart.hasData()) {
    chart.hideNoData();
    chart.showNoData("Your custom error message");
}

probably these methods are not available for the highcharts version I am using.

Thanks to @Pandiyan for fixing the issue with the stackBlitz import.

UPDATE: When locally I try to change NoDataToDisplay import from,

import * as noDataToDisplay from 'highcharts/modules/no-data-to-display.src';

to,

import NoDataToDisplay from 'highcharts/modules/no-data-to-display';

I get the following import error.

enter image description here

due to which I am getting the following errors, when I try to follow @daniel_s answer.

enter image description here

All of my dependencies are in sync, with the provided stackBlitz. I also

  • removed my node_modules folder and re installed all my dependencies.
  • Updated @types/highcharts to the latest version.
Saif
  • 1,745
  • 5
  • 23
  • 46

3 Answers3

8
  1. What is the proper way of using noData option with angular 5
  2. How to make sure it appears consistently? probably different configuration like setData([]) or setData(null) makes it appears in consistently, but I am not able to find out one root cause behind its inconsistency.
  3. How can I toggle noData message dynamically.

Re 1. The noData module should work automatically, so if you will add some point to one of your currently visible series, then the "no-data" message disappears. Similarly, when you remove() the series points, so that the series will be empty, then the "no-message" information will be visible on the chart. In case of using it manually, of course you can do it just like you mentioned above. Here is the simple example of use (with buttons included): https://stackblitz.com/edit/highcharts-toggling-nodata-w5fwkf

Re 2. Looks fine if using setData([]) and setData(null). Here is the example: https://stackblitz.com/edit/highcharts-toggling-nodata-54xrqh . If you mean something different, could you describe your question more precisely?

Re 3. If you mean change the noData message dynamically, you should set the chart.options.lang.noData property equal to some new string, then call chart.hideNoData() and chart.showNoData to refresh element value. Here is the example applied to the ng: https://stackblitz.com/edit/highcharts-toggling-nodata-hwnzcl

[EDIT]

Refering to your question update, in order to use a specific module directly within component and not by setting it in providers, just delete the { provide: HIGHCHARTS_MODULES, useFactory: () => [NoDataToDisplay] } from app.module.ts file, and load appropriate module in app.component.ts using require() syntax, like below:

import Highcharts from 'highcharts';

const noData = require('highcharts/modules/no-data-to-display')
noData(Highcharts)

Live example: https://stackblitz.com/edit/highcharts-toggling-nodata-muxx9s

Kind regards!

**

daniel_s
  • 3,635
  • 1
  • 8
  • 24
  • I guess the root cause of all these three issues, comes down to the way I am importing noData. All my local dependencies are in sync with the stackblitz, when locally I try to import noDataToDisplay the way mentioned by @pandiyan I am getting "@types/highcharts/modules/no-data-to-display"' has no default export." but its working fine in the stackBlitz. I am updating my question with further details. – Saif Oct 09 '18 at 07:54
  • I've just edited my answer. Please take a look at it. – daniel_s Oct 09 '18 at 09:59
  • I am confused regarding "noDataToDisplay(Highcharts)", I am getting "chartModule is not a function" run time error, when I update your stackBlitz with this. Can you provide a working stackBlitz may be? Thanks alot for all this help. – Saif Oct 09 '18 at 12:45
  • Updated second time. Sorry for misunderstand. – daniel_s Oct 10 '18 at 10:02
  • thanks, for all your help. One last thing though, I'll have to do "noData(Highcharts)" in every component which is using highcharts? I guess I can do this in the module's constructor as well? But don't know how its gonna turn out for lazy loaded modules. previous approach was great in the sense that noData was being added into the module providers, and in case of lazy loaded modules provided factory remained singleton through out the app. In short I didn't had to do that for each module. I do have a shared module as well, may be I could incorporate this into that? – Saif Oct 10 '18 at 10:22
  • You asked about using the modules within component (locally), so I've adjusted the answer for your needs, but it is possible that I didn't understood you well. Of course, the best way out of that is by defining the provider for modules. Then all your components has the `noData` module loaded on their prototypes. – daniel_s Oct 10 '18 at 11:21
3

Try out this

import NoDataToDisplay from 'highcharts/modules/no-data-to-display';

...

{ provide: HIGHCHARTS_MODULES, useFactory: () => [NoDataToDisplay] }  

Slackblitz

Pandiyan Cool
  • 6,381
  • 8
  • 51
  • 87
0

Try this:

import { default as NoData } from 'highcharts/modules/no-data-to-display';
NoData(Highcharts);