You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 8, 2020. It is now read-only.
Repository navigation
This repository was archived by the owner on Apr 8, 2020. It is now read-only.
Hopefully this question is not too off topic, but I'm getting a really weird issue with the yo aspnetcore-spa template when trying to use d3.js with it. The issue seems to be somehow linked to something in the template because the same code doesn't have the behaviour in an Angular CLI project.
I'm using d3.js to display a simple bar chart I found as an example online. It's a component that imports d3 and uses it to add an SVG and create the bar chart. When I access it through a link I added to the template's left menu, everything works fine, the chart is displayed just fine. But, if I try to access it directly through the URL I've configured as route for the component, I get this exception thrown:
Exception: Call to Node module failed with error: TypeError: Cannot read property 'createElementNS' of undefined
at Object.<anonymous> (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:9352:33)
at Object.<anonymous> (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:10129:39)
at Selection.selection_select [as select] (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:9561:53)
at Selection.selection_append [as append] (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:10128:18)
at BarchartComponent.createChart (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:474:39)
at BarchartComponent.ngOnInit (C:\sources\d3NetCoreAngular2\ClientApp\dist\main-server.js:460:15)
at AppView._View_BarchartComponent_Host0.detectChangesInternal (BarchartComponent_Host.ngfactory.js:28:86)
at AppView.detectChanges (C:\sources\d3NetCoreAngular2\ClientApp\dist\vendor.js:12652:19)
at AppView.detectContentChildrenChanges (C:\sources\d3NetCoreAngular2\ClientApp\dist\vendor.js:12670:24)
at AppView.detectChangesInternal (C:\sources\d3NetCoreAngular2\ClientApp\dist\vendor.js:12662:19)
I'm really lost as to why there would be a difference between accessing the component through a link or directly. Could it be because of a server-side pre-rendering? Is there something else in the template that would make a difference between the two ways of accessing? I've tried adding a breakpoint in the typescript, if I access through the link, the breakpoint is triggered and the code stopped, but if I access directly (or if I refresh the page), then the breakpoint is not triggered and I get the exception.
Here are the important parts of the component's typescript:
Can you try wrapping the logic inside of the ngOnInit with the code below and see if it works? D3 doesn't readily get rendered on the server so you might have to make sure it's only rendered on the client.
import { isBrowser } from 'angular2-universal'; // add this uptop
if (isBrowser) {
// your d3 code
}
Well when you refresh, or type an address and press enter you're hitting the server side, which in turn tries to render that specific section of the application with Angular Universal. Once that's rendered to a string and loaded on the page, the client-side bootstrap starts and then takes over, and the rest of the your time navigating is like a normal SPA. But because of that initial server side render, you get performance boosts, real SEO (since all crawlers can reach your site now), and deep-linking (think social media sharing), all at your finger tips.
You just have to always keep in mind how your code / components will be handled on the server(Node) side, and you'll be good to go :)
Activity
MarkPieszak commentedon Dec 7, 2016
Can you try wrapping the logic inside of the ngOnInit with the code below and see if it works? D3 doesn't readily get rendered on the server so you might have to make sure it's only rendered on the client.
Gimly commentedon Dec 7, 2016
Thanks! It does work indeed!
I fought that issue for nearly a week, and it's fixed in just a line... 👍 Oh well, that's how you learn.
Does it mean that my guess was correct? When I access the URL directly, the code is pre-rendered server-side?
Care to explain what in the template activates that server-side rendering?
MarkPieszak commentedon Dec 7, 2016
Well when you refresh, or type an address and press enter you're hitting the server side, which in turn tries to render that specific section of the application with Angular Universal. Once that's rendered to a string and loaded on the page, the client-side bootstrap starts and then takes over, and the rest of the your time navigating is like a normal SPA. But because of that initial server side render, you get performance boosts, real SEO (since all crawlers can reach your site now), and deep-linking (think social media sharing), all at your finger tips.
You just have to always keep in mind how your code / components will be handled on the server(Node) side, and you'll be good to go :)
SteveSandersonMS commentedon Dec 8, 2016
Thanks for resolving this @MarkPieszak!
Gimly commentedon Dec 8, 2016
Thanks a lot for your help and explanation @MarkPieszak.
flaneuse commentedon Nov 29, 2018
FYI
isBrowser()has been switched toisPlatformBrowser. See Angular Universal Gotchas