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

Render on server e.g. integrate into angular universal? #173

Open
crebuh opened this issue Oct 3, 2016 · 32 comments
Open

Render on server e.g. integrate into angular universal? #173

crebuh opened this issue Oct 3, 2016 · 32 comments

Comments

@crebuh
Copy link

crebuh commented Oct 3, 2016

[ x] feature request
[ x] support request => Please do not submit support request here

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?

@amcdnl
Copy link
Contributor

amcdnl commented Oct 3, 2016

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.

@crebuh
Copy link
Author

crebuh commented Oct 4, 2016

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?

@PatrickJS
Copy link

I can help with some advice on this

@amcdnl
Copy link
Contributor

amcdnl commented Oct 6, 2016

@gdi2290 - Ears are wide open :)

@Quixomatic
Copy link

@amcdnl @gdi2290 any updates on this issue? since document is not defined on the server side it throws errors when using with angular-universal

@amcdnl
Copy link
Contributor

amcdnl commented Oct 12, 2016

@Quixomatic - where is the document reference breaking it?

@Quixomatic
Copy link

/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

@Quixomatic
Copy link

@amcdnl any thoughts on this?

@scotteby
Copy link

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.

@Quixomatic
Copy link

Quixomatic commented Oct 23, 2016

@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.

@Quixomatic
Copy link

I also added nested my component inside of a div with a *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.

@amcdnl
Copy link
Contributor

amcdnl commented Oct 24, 2016

@gdi2290 Is there better ways to get reference to the window using the renderer or something?

@Quixomatic
Copy link

@amcdnl Think they're working on implementing jsdom into the server side of things to make all of this easier.

@scotteby
Copy link

scotteby commented Oct 24, 2016

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;
    }
}

@Quixomatic
Copy link

@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()"

@scotteby
Copy link

Thanks for the suggestion, that does make it a little easier to implement.

@andreschort
Copy link

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?

@csy9
Copy link

csy9 commented Jan 23, 2017

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!

@Crewski
Copy link

Crewski commented Feb 21, 2017

@andreschort I am getting the same issue. Simply importing NgxDatatableModule is causing the exception.

@rezidual
Copy link

rezidual commented Mar 9, 2017

@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.

@amcdnl
Copy link
Contributor

amcdnl commented Apr 15, 2017

I believe this is working in latest. Can anyone confirm? We aren't manipulating any dom or using document directly anymore.

@scotteby
Copy link

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

@scotteby
Copy link

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?

@amcdnl
Copy link
Contributor

amcdnl commented May 5, 2017

Can you PR that back plz?? @scotteby

@earlyster
Copy link
Contributor

earlyster commented Oct 10, 2017

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

@wizarrc
Copy link
Contributor

wizarrc commented Oct 10, 2017

@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.

@manzonif
Copy link

manzonif commented Nov 3, 2017

Hi,
I get this error message in SSR:

 this.document.createElement is not a function
          at ScrollbarHelper.getWidth

@dllabs
Copy link

dllabs commented Nov 24, 2017

@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

@earlyster
Copy link
Contributor

@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.

@earlyster
Copy link
Contributor

I have created a pull request here - #1178

@devparag
Copy link

Please look into this issue..#1038

@devparag
Copy link

@amcdnl Please look into this issue..#1038

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