4

I'm using AngularJS and FusionCharts together in my web application. The upcoming release of AngularJS v1.3.0 will require there to be a <base> tag in the HTML head, so as to resolve all relative links, regardless of where the app is hosted in the site's directory.

When including the <base> tag with the latest version of FusionCharts (currently v3.4.0), the 3D charts do not render properly. For example, a 3D pie chart appears and has rotation and clickable slices, as well as tooltips and color on the inside edges of the slices. However, the entire outer color is black.enter image description here

Excluding the <base> tag causes the chart to look and behave normally.

Does anyone have any idea how to resolve this? Unfortunately, I don't own the source code, otherwise I'd hack at it myself.

Here's the link to the non-working jsFiddle: http://jsfiddle.net/aaronaudic/59Bmf/207

SOLUTION:

I originally awarded the correct solution to @pankaj, because his solution of simply adding the following line at page load seemed to fix the problem:

document.getElementsByTagName("base")[0].setAttribute("href", window.location.pathname+window.location.search);

However, this only works if the charts are on the initially-loaded page (when user navigates directly to page with the charts); when navigating to the page by way of something like ui-router, I was still seeing black.

The correct answer is from @Shamasis. Adding the following to the page load will fix the issue application-wide:

eve.on('raphael.new', function () {
    this.raphael._url = this.raphael._g.win.location.href.replace(/#.*?$/, '');
});

His original caveat mentioned that the export functions may be hampered from the Cloud, and this may be (I don't export from the cloud). However, exporting locally, as can be observed in this jsFiddle, works perfectly well: http://jsfiddle.net/aaronaudic/Gs6sN/14

My base tag, in the head of the page, is simply:

<base href="/">
Aaron Jessen
  • 404
  • 5
  • 14
  • Check the styles applied, look in the network panel for failed requests for CSS files, perhaps something in Fusion Charts needs to be updated to use an absolute path. If you see any 404s in the console or network panel in chrome debugging tools then you could submit a bug report to Fusion Charts or search the source for said URL and fix it. – shaunhusain Sep 07 '14 at 18:54
  • Can you put the code on jsfiddle? – pankaj Sep 07 '14 at 19:11
  • @pankaj Here's the most basic example of the problem http://jsfiddle.net/aaronaudic/59Bmf/207/. All I did was take FusionChart's own example and added a tag in a head section. Removing it will fixes problem. This issue apparently exists without AngularJS, so for now, just ignore that aspect. – Aaron Jessen Sep 07 '14 at 19:20
  • Any hints for Angular 2+? I couldn't find a way to get a `eve` reference. – Bruno Medeiros Mar 25 '19 at 10:52

5 Answers5

5

The issue is not primarily with FusionCharts - it is a generic SVG issue. In SVG, when gradient colour is applied on an element, it actually "refers" to another gradient element on the page. This is somewhat similar to how links can refer to hashtags using <a id="hash" /> on a page.

Now, when you are setting a <base> to the page, the references are going haywire. The gradients now refer to an element with URL as provided in your base tag.

One way to fix this is to access the internal graphics renderer and hard-set the URL to the absolute location of the page. The way to do that would be to access RedRaphael object within FusionCharts core and set the _url variable for the same.

The following code should do it for you.

eve.on('raphael.new', function () {
    this.raphael._url = this.raphael._g.win.location.href.replace(/#.*?$/, '');
});

The only caveat is that specifying absolute URL as reference to gradient elements does not work in some older browsers (I'm not sure exactly - could be Safari 5 or FF 3.0). It may also have some negative impact while exporting FusionCharts as image - the relative URLS will be invalidated when the SVG is rasterised on FusionCharts Cloud Export servers.

Shamasis Bhattacharya
  • 3,392
  • 3
  • 20
  • 24
  • I originally awarded the answer to @pankaj, because his base tag manipulation worked if the currently-loaded page contains the charts. But, if you navigate to the page from another page (e.g. by using the 3rd-party Angular ui-router directive), the charts were still black. Your solution is the only one that works across the entire SPA. While I cannot confirm your caveat about exporting from the cloud, I did a test here http://jsfiddle.net/aaronaudic/Gs6sN/14 to prove that the export does work locally. Cheers! – Aaron Jessen Sep 08 '14 at 12:19
  • excellent solution. I was facing issue when I migrated from Fusionchart 3.3.1 which was using canvas for rendering to 3.4 – Anirudha Apr 27 '17 at 06:57
  • Thank you Shamasis. This solution solved my problem in Ionic 4 + Angular 8 project. I just added this inside my app.component.ts `import { Component } from '@angular/core';` `declare var eve;` `@Component({...})` `export class AppComponent {` ` constructor( ) { this.initializeApp(); }` ` initializeApp() {` ` this.platform.ready().then(() => {` ` this.statusBar.styleDefault();` ` this.splashScreen.hide();` ` eve.on('raphael.new', function() {` ` this.raphael._url = this.raphael._g.win.location.href.replace(/#.*?$/, '');` ` });});}}` – Fehim Dec 18 '19 at 19:55
3

I'm fixing this problem on Angular 7 and FusionCharts here, FusionCharts.options.SVGDefinitionURL='absolute' didn't help much. It fixed Safari, but just on the first route with pie charts. Any further navigation would break again, and now Chrome is also broken after navigating.

I considered the Raphael workaround, but couldn't find a way to get a eve reference, so I decided to try removing the baseHref, which seems to be the "cause" of the problem.

Here is what I did:

  1. Removed the base from index.html (left it there commented so everyone knows why) and also put the favicon as an absolute resource.
    <!-- Configuring deployUrl and APP_BASE_HREF in the main module, 
         see [[this stackoverflow link]] -->
    <!--<base href="/">-->
    ...
    <link rel="icon" type="image/x-icon" href="/favicon.ico">
  1. Configured deployUrl on angular.json (see this question)

I'm using multiple projects layout here, so for me it was added on path projects.my-project.architect.build.options.deployUrl, should be simpler in the default project.

    "deployUrl": "/",
  1. Configured my app module to inject the configuration for the router (docs)
import { APP_BASE_HREF } from '@angular/common'
...

@NgModule({
    ...
    providers: [
        { provide: APP_BASE_HREF, useValue: '/' },
        ...
    ],
    ...
})

Everything looks good now, all browsers work, Angular router seems to be working fine as well.

Bruno Medeiros
  • 2,251
  • 21
  • 34
  • Android its working fine, in iOS i am getting black color pie & donut charts, I have implemented your solution, now my issue has been fixed, Thanks for your solution. – Mohan Apr 02 '19 at 10:26
2

TLDR: set FusionCharts.options.SVGDefinitionURL='absolute'; in your JavaScript to fix this problem

Detailed:

There is a FusionChart solution to this.

The problem you mention comes from SVG using relative references to things like gradients, resolving incorrectly due to the tag being present.

This problem is described on https://github.com/angular/angular.js/issues/8934. One possible solution would be setting $locationProvider.html5Mode({ enabled: true, requireBase: false }); and using absolute paths.

Although this does solve the problem there is a solution by FusionCharts by setting FusionCharts.options.SVGDefinitionURL='absolute'; in your JavaScript. (http://www.fusioncharts.com/dev/api/fusioncharts/fusioncharts-properties.html#FusionCharts.options-attributes-SVGDefinitionURL)

Aides
  • 3,643
  • 5
  • 23
  • 39
0

You can simply set absolute url in base tag

document.getElementsByTagName("base")[0].setAttribute("href", window.location.pathname+window.location.search);

Here is jsfiddle: http://jsfiddle.net/59Bmf/208/

In angular you can use bind the url using a property in controller.

$scope.absurl=$location.absUrl()

And use it inside view

<base href="{{absurl}}">
pankaj
  • 474
  • 5
  • 15
  • Okay @pankaj, the first part of your answer works if the page with the chart(s) is the initially-loaded page. But, when navigating from another page, to the page with the charts, by way of ui-router, the charts are black again. Can you explain where and how I am to use the $scope.absurl=$location.absUrl() portion? Do I implement that with every controller? – Aaron Jessen Sep 07 '14 at 23:24
0

@Shamasis Bhattacharya saved my life.

This solution solved my problem with fusioncharts in Ionic4+Angular8 project.

This is what I did in app.component.ts component:

import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';

declare var eve;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  constructor() {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      eve.on('raphael.new', function() {
        this.raphael._url = this.raphael._g.win.location.href.replace(/#.*?$/, '');
      });
    });
  }
}
Fehim
  • 51
  • 1
  • 3