CaliStyle / ng-intercom

Angular 7+ Wrapper for Intercom.com
MIT License
54 stars 46 forks source link

ReferenceError: document is not defined #34

Closed RikdeVos closed 6 years ago

RikdeVos commented 6 years ago

The intercom package is referencing the document which is a bad practise when using Angular. In my case it results in an error as I use Angular Universal to compile the app.

wbhob commented 6 years ago

This is a direct port of the Intercom loading script. If you have a suggestion, I would be open to reviewing a pull request.

RuiEEE commented 6 years ago

I'm getting the same issue and I'm guessing this is a SSR issue, can we make this happen? Prevent the server side to run the intercom loading script perhaps?

wbhob commented 6 years ago

If you don't run the loading script, then the Intercom library won't load at all. You'll notice that the Intercom provider is an Angular-friendly wrapper around existing intercom methods. Unless someone knows a way to load the official intercom script at runtime, I don't think this will be available out of the box.

wildlifechorus commented 6 years ago

I'm not gonna go into much detail but this is pretty simple.

  1. Remove this third party, since it does not work on Angular 5.
  2. On you app.component.ts add the following inside ngOnInit():
    // Init Intercom
    if (isPlatformBrowser(this.platformId)) {
      const d = document;
      const s = d.createElement('script');
      s.type = 'text/javascript';
      s.async = true;
      s.src = `https://widget.intercom.io/widget/` + environment.intercomId;
      const x = d.getElementsByTagName('script')[0];
      x.parentNode.insertBefore(s, x);

      const w = <any>window;
      w.intercomSettings = {
        app_id: environment.intercomId,
        widget: {
          'activator': '#intercom'
        },
        custom_launcher_selector: '#intercom_launcher'
      };
    }

This will work with Angular 5 SSR/AOT!

Don't forget to use:

import { isPlatformBrowser } from '@angular/common';

scott-wyatt commented 6 years ago

@wbhob, we could move this lib into a modified boilerplate of https://github.com/CaliStyle/NgEngine. That has SSR/AOT testing built into it and ng-packagr to deploy libraries.

wbhob commented 6 years ago

the issue is that Intercom depends directly on document to inject the intercom messenger script and modify the DOM to insert the messenger button. Other than working directly with intercom, I can't think of any way to support SSR.

scott-wyatt commented 6 years ago

So, when I built this originally, I used dependency injection. On the server side it would just use a bunch of noops, render correctly and then carry out the client side intercom boot when angular does it's startup on the client side. You can also do this by what @wildlifechorus was talking about, by checking if the environment is the browser and not the server. You don't want to render the intercom button on the server anyhow.

wbhob commented 6 years ago

I guess my question is: how do we render intercom if it is in a server-side context? We still want consumers to be able to use Intercom, so how to we go about including the intercom script?

scott-wyatt commented 6 years ago

Angular reboots even if it’s rendered server side, no worries mang, I can prove it and show it :-)

wbhob commented 6 years ago

Sounds awesome

scott-wyatt commented 6 years ago

Closing this as fixed in 1.0.0-beta.12, however beta.12 is having it's own issues.