tb / ng2-nouislider

Angular2 noUiSlider directive
http://tb.github.io/ng2-nouislider/
MIT License
184 stars 114 forks source link

SSR: ERROR ReferenceError: document is not defined #185

Open vsilva472 opened 6 years ago

vsilva472 commented 6 years ago

After compile without errors with SSR when get serve up an error appears on console and theres no component rendered inside view.

The error is the following: Node server listening on http://localhost:4000 Running on the server with appId=rje-frontend ERROR ReferenceError: document is not defined at testOptions (C:\rjefrontend\dist\server.js:152857:11) at Object.initialize [as create] (C:\rjefrontend\dist\server.js:154277:17) at NouisliderComponent.ngOnInit (C:\rjefrontend\dist\server.js:151805:34) at checkAndUpdateDirectiveInline (C:\rjefrontend\dist\server.js:12909:19) at checkAndUpdateNodeInline (C:\rjefrontend\dist\server.js:14173:20) at checkAndUpdateNode (C:\rjefrontend\dist\server.js:14135:16) at prodCheckAndUpdateNode (C:\rjefrontend\dist\server.js:14675:5) at Object.updateDirectives (C:\rjefrontend\dist\server.js:53509:4282) at Object.updateDirectives (C:\rjefrontend\dist\server.js:14464:72) at checkAndUpdateView (C:\rjefrontend\dist\server.js:14117:14)

SSR implemented by the angular oficial tutorial Is there one way to make this awesome plugin work with Angular Universal?

Plugin version from package.json { "ng2-nouislider": "^1.7.11" "nouislider": "^11.1.0 }

Details of my environment: Angular CLI: 6.0.8 Node: 8.11.1 OS: win32 x64 Angular: 6.0.7

EDIT: After look inside server.js at line 152857 i found a try to create a htmlElement: var d = document.createElement("div");

I think this is part of core of nouislider.js. Is there one way to edit this to use angular way instead direct access to dom or bypass this only from SSR?

alexnoise79 commented 6 years ago

Same issue here

KxL51 commented 6 years ago

Same issue, someone have an idea?

adskiremote commented 5 years ago

I found a suitable workaround that isn't perfect but will help to fix SSR issues.

Simply prevent the slider from appearing when rendered by the server and use in only isPlatformBrowser().

You can do this using a AppShellNoRender Directive. I took the following example from here: https://blog.angular-university.io/angular-universal/

This is my directive

import {Directive, Inject, OnInit, PLATFORM_ID, TemplateRef, ViewContainerRef} from '@angular/core';
import {isPlatformServer} from '@angular/common';

@Directive({
    selector: '[appShellNoRender]'
})
export class AppShellNoRenderDirective implements OnInit {

    constructor(
        private viewContainer: ViewContainerRef,
        private templateRef: TemplateRef<any>,
        @Inject(PLATFORM_ID) private platformId
    ) { }

    ngOnInit() {
        console.log('Is Server:', isPlatformServer(this.platformId));
        if (isPlatformServer(this.platformId)) {
            this.viewContainer.clear();
        } else {
            this.viewContainer.createEmbeddedView(this.templateRef);
        }

    }
}

And applied to my noUislider...

<nouislider #priceRange [config]="priceRangeConfig" formControlName="priceRange" class="price-range" fxFlex fxFlex.xs="none" *appShellNoRender></nouislider>

Now when rendered by the server the document not found error doesn't appear as noUIslider is removed.

However when using a browser it will appear.

I hope this helps :-)