Open crebuh opened 7 years ago
I haven't had a need for universal support but happy to accept a PR for it. I'm sure its got some minor tweaks and it would work.
of course I would make a PR, I'm just a bit new to the universal environment. Are there any sample implementations for similar scenarios or do you have any advice how to shim/inject specific functionality depending on the environment?
I can help with some advice on this
@gdi2290 - Ears are wide open :)
@amcdnl @gdi2290 any updates on this issue? since document is not defined on the server side it throws errors when using with angular-universal
@Quixomatic - where is the document reference breaking it?
/node_modules/angular2-data-table/release/index.umd.js:285 var testStyle = document.createElement('div').style; ^
ReferenceError: document is not defined at /home/ubuntu/workspace/node_modules/angular2-data-table/release/index.umd.js:285:17
@amcdnl any thoughts on this?
I would love to use this data table, it looks fantastic, but I'm getting the same error. Is there anyway I can implement a workaround to get your data table working in my application?
Thanks.
@scotteby I was able to get this working with angular-universal with a bit of a temporary hack:
In the release folder if you open index.js and replace the following lines:
line 3199:
var testStyle = typeof document != 'undefined' ? document.createElement('div').style : [];
line 3203:
var styles = typeof window != 'undefined' ? window.getComputedStyle(document.documentElement, '') : [];
line 3204:
var pre = typeof window != 'undefined' ? (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/))[1] : null;
line 3205:
var dom = typeof window != 'undefined' ? ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1] : null;
line 3210:
js: typeof window != 'undefined' ? pre[0].toUpperCase() + pre.substr(1): ''
line 3581:
var ua = typeof window != 'undefined' ? window.navigator.userAgent : null;
tldr; I added conditions that check to see if global objects like window/document are undefined, if so don't do the normal stuff, do the angular-universal safe stuff instead.
I also added nested my *ngIf="isBrowser"
isBrowser being a boolean variable that you can import from angular-universal that will not render the datatable component until you're loading things on the client side.
@gdi2290 Is there better ways to get reference to the window using the renderer or something?
@amcdnl Think they're working on implementing jsdom into the server side of things to make all of this easier.
Thanks @Quixomatic , this works great in our app now. Really appreciate the quick turnaround on providing a fix for us.
By the way, I did have to set the isBrowser flag to true in the ngOnInit method inside my component to get the table to render.
import { isBrowser } from 'angular2-universal';
export class MyComponent {
isBrowser;
ngOnInit()
{
this.isBrowser = true;
}
}
@scotteby this function worked fine for me after importing isBrowser into a shared service, would work importing into a component and defining the function there as well.
isBrowser () {
return isBrowser
}
Then my *ngIf="isBrowser()"
Thanks for the suggestion, that does make it a little easier to implement.
I'm trying to use the isBrowser workaround but I get the exception by just importing NgxDatatableModule into my app module. Any ideas on what am I missing?
I am having some trouble resolving what I believe to be a related issue, while trying to update from angular2-data-table (1.7.0) to ngx-datatable (5.0.0). Still using universal. Changing index.js to check for undefined document/window as shown earlier has fixed the "document/window not defined" exceptions, but now I am stuck on a similar exception:
ReferenceError: MouseEvent is not defined at ...\release\index.js:1301:42
Any advice on how to finish patching index.js for the new version would be greatly appreciated!
@andreschort I am getting the same issue. Simply importing NgxDatatableModule is causing the exception.
@amcdnl are there any updates regarding support for Angular Universal? This is an amazing component and it would be great to be able to leverage the server-side rendering capabilities of Universal for improved performance.
I believe this is working in latest. Can anyone confirm? We aren't manipulating any dom or using document directly anymore.
I just tested this using ngx-datatable 8.0.0 with Angular 4.0.2 and still get an error when it tries to render on the server.
Exception: Call to Node module failed with error: Prerendering failed because of error: ReferenceError: document is not defined at Object../src/utils/prefixes.ts
I just went through the entire code and got it working with Universal server side rendering, but had to add a check for all the undefined Window, Document, MouseEvent, and Keyboard event references in the following files:
prefixes.ts translate.ts elm-from-point.ts body-cell.component.ts body-row-wrapper.component.ts long-press.directive.ts resizeable.directive.ts
Is it too much of a hack to just add those undefined checks into the source?
Can you PR that back plz?? @scotteby
I was trying to render ngx-datatable using ng4 and noticed issues with 2 things .. scrollBar width .. I found a way to use DI to replace service (with manual changes locally) to get the scrollbar width based on server param / user agent. Next I am running into issues with DataTable.recalculateDims trying to use
var dims = this.element.getBoundingClientRect();
This is causing error in server side rendering
It looks like width and height of grid element must be determined up front for server side rendering to work. I am thinking I can separate this into a service and DI to inject the expected dimensions if client passes the viewport height / width as a server param.
Thoughts?
And thank you for open sourcing this component
@earlyster one thing I noticed with scrollbar width is that they are browser specific. You could very well set the width to the most popular browser and adjust after the server rendering if it's not correct. Another would be for the server side rendering to know which browser it's talking to cough agent string, and have a pre-computed width for each vendor, with a default fall-through for unknown.
Another approach altogether is to virtualize the scrollbar and make it a theme instead, allowing the developer to pick how the scrollbar looks.
Hi, I get this error message in SSR:
this.document.createElement is not a function
at ScrollbarHelper.getWidth
@earlyster Did you solve your issues with var dims = this.element.getBoundingClientRect();
?
I'm hitting up against this error too, and I'd be happy with your solution where the viewport width is passed as a server param. (As for viewport height, my table just needs to be as long as it needs to be given the width and the dataset length. I guess I could get away with just passing some arbitrarily very long viewport height?)
thanks
@dllabs - sorry for delay in response. Yes I have forked ngx-datatable and then injected different implementations for server of ScrollbarHelper.getWidth -- in my server implementation I have used a cookie approach where client viewport info is provided. I was originally thinking of user agent approach but there are way too many user agents so cookie. I took the same idea that is used for responsive images -- https://github.com/igrigorik/http-client-hints.
I have created a pull request here - https://github.com/swimlane/ngx-datatable/pull/1178
Please look into this issue..#1038
@amcdnl Please look into this issue..#1038
Is it possible to use this component with project like angular universal and render the tables already on the server. And on the client using the sorting and filtering stuff? I tried to integrate it into my universal project without success, because the component of course is accessing the window document object.
Any solutions or ideas on that or is it not supposed to do this?