Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chart width exceeds element using Angular Material Tabs #217

Closed
jer-tx opened this issue Aug 3, 2020 · 7 comments
Closed

Chart width exceeds element using Angular Material Tabs #217

jer-tx opened this issue Aug 3, 2020 · 7 comments

Comments

@jer-tx
Copy link

jer-tx commented Aug 3, 2020

Describe the bug

On first page load, width of chart exceeds the available width set by parent div when inside Angular Material tab. Graph resizes properly when viewport size changes.

Expected behavior

Width of chart should be correct on first page load

Demo

https://github.com/jer-tx/highcharts-angular-material-issue

Setup used

  • NodeJS version 12.14.0
  • Angular version 9.0.1
  • TypeScript version 3.7.5
    etc.

Example:

Using example data from highcharts. All elements are within 90% width div. First graph is outside of mat-tab-group. Second graph is within a tab. If window gets resized, chart snaps into proper width.
chrome_Mc2Mdkp6qk

@mateuszkornecki
Copy link
Contributor

Thanks for reporting the issue @jer-tx . It is probably related to #149. As a workaround, you could try to call the chart.reflow() on the chart's callback function.

  chartCallback: Highcharts.ChartCallbackFunction = function (chart): void {
        setTimeout(() => {
            chart.reflow();
        },0);
    }

I am closing, for now, since the problem looks very similar to the already reported one. But feel free to reopen the ticket if the proposed solution won't work for you.

@jer-tx
Copy link
Author

jer-tx commented Aug 8, 2020

That solution doesn't appear to be working here.

@mateuszkornecki
Copy link
Contributor

mateuszkornecki commented Aug 10, 2020

I cloned your repository and everything was working correctly after I applied that solution.

//app.component.ts
  chartCallback: Highcharts.ChartCallbackFunction = function (chart): void {
    setTimeout(() => {
        chart.reflow();
    },0);
};
//app.component.html
<div style="width: 90%">
  <mat-tab-group mat-align-tabs="center">
    <mat-tab label="First">
      <highcharts-chart [Highcharts]="Highcharts" [options]="chartOpts" [callbackFunction]="chartCallback" style="display: flex"></highcharts-chart>
    </mat-tab>
  </mat-tab-group>
</div>

Are you sure that you passed the chartCallback to the callbackFunction input?

@jer-tx
Copy link
Author

jer-tx commented Aug 10, 2020

Hm. Working on that repo like you said so I went back in our real implementation to see what might be different.

We have, as you might expect, more than 1 tab. So, when navigating to the second tab, that's where this solution doesn't seem to work.

I've updated the repo to include another tab and the callback.

@mateuszkornecki
Copy link
Contributor

mateuszkornecki commented Aug 10, 2020

That's still the same problem, caused by the display: flex. It's a known behavior related more to the Highcharts itself than to the 'highcharts-angular' wrapper. If you want to read more about it I will encourage you to check out this thread: highcharts/highcharts#6427.

I am not 100% sure why the workaround with the chartCallback doesn't work with the tabs. I managed to fix that by calling the chart.reflow() on the mat-tab-group selectedTabChange event.

  chartRef: Highcharts.Chart;
  chartCallback: Highcharts.ChartCallbackFunction = (chart): void => {
    this.chartRef = chart;
    setTimeout(() => {
      this.chartRef.reflow();
    }, 0)
  };

  handleChange($event): void {
    this.chartRef.reflow();
  }
<div style="width: 90%">
  <mat-tab-group mat-align-tabs="center" (selectedTabChange)="handleChange($event)">
    <mat-tab label="First">
    </mat-tab>
    <mat-tab label="Second">
      <highcharts-chart [Highcharts]="Highcharts" [options]="chartOpts" [callbackFunction]="chartCallback" style="display: flex;"></highcharts-chart>
    </mat-tab>
  </mat-tab-group>
</div>

@jer-tx
Copy link
Author

jer-tx commented Aug 10, 2020

Interesting. I was trying to figure out a way to run the reflow on tab change but didn't know how to reference that specific chart instance. Didn't even think to just store it once the first callback is ran.

This is working for me, thank you!

For posterity/complete solution: I'm running this in an angular tab that then references another component for the actual chart (we use this component/chart elsewhere). I'm passing the tab event into the component, and that ultimately runs the reflow.

On the component housing the angular tabs:

// mycomponent.html
<mat-tab-group mat-align-tabs="center" (selectedTabChange)="handleChange($event)">
<mat-tab>
    <ng-template mat-tab-label>
	My chart
    </ng-template>
	<my-chart [chartData]="activityData"  [tabEvent]="tabEvent"></my-chart>
</mat-tab>

// mycomponent.ts
tabEvent;
handleChange(event){
	this.tabEvent = event
}

Then on the component housing the chart, provide the tabEvent input:

@Input() set tabEvent(event){
	this.handleChange(event)
}
chartCallback: Highcharts.ChartCallbackFunction = (chart): void => {
		this.chartRef = chart;
		setTimeout(() => {
			this.chartRef.reflow();
		}, 0)
	};
handleChange($event): void {
	this.chartRef.reflow();
}

@mateuszkornecki
Copy link
Contributor

Closing, since the issue seems to be resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants