2

I am embedding a Calendly widget into a simple Angular application. It works in Chrome, Firefox, and Edge, but just shows a blank white box in IE.

The working url for the site is https://cei-demo.firebaseapp.com/schedule-an-appointment

I have tried using innerHTML to render the HTML code from the component and not in the template. I had the same problem.

calendly.component.html

<div class="my-5 p-3 container bg-white text-dark">
  <div class="calendly-inline-widget" data-url="https://calendly.com/test-cei" style="min-width:320px;height:700px;"></div>
</div>

index.html (right above the body tag)

<script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js"></script>

I would like the widget to display in all browsers.

Here is the code in response to Dmitry Pashkevich below:

component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-calendly',
  templateUrl: './calendly.component.html',
  styleUrls: ['./calendly.component.css']
})
export class CalendlyComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
}

component.html

<div class="my-5 p-3 container bg-white text-dark">
  <div class="calendly-inline-widget" style="min-width:320px;height:580px;" data-auto-load="false">
</div> 

index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Carbon Emery Insurance</title>
  <base href="/">
  <!-- reCaptcha -->
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>

  <!-- Custom Fonts -->
  <link href="https://fonts.googleapis.com/css?family=Lato|Montserrat" rel="stylesheet">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="./assets/favicon.ico">

  <!-- Bootstrap core CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

  <!-- Font Awesome -->
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">

</head>
<body>
  <app-root></app-root>

  <!-- Bootstrap js -->
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  <script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js"></script>
  <script>
    Calendly.initInlineWidget({
    url: 'https://calendly.com/test-cei',
    parentElement: document.querySelector('.calendly-inline-widget'),
    });
  </script>
</body>
</html>
wingej0
  • 25
  • 1
  • 7

1 Answers1

8

Welcome to StackOverflow, @wingej0.

There is a special JavaScript API for invoking Calendly widgets from single-page applications in Angular, React, etc. With this API, you can control exactly when you want the widget to be initialized, instead of having it initialize upon page load.

General instructions

First, add a data-auto-load="false" attribute to the .calendly-inline-widget and remove the data-url attribute. So the element should look like this:

<div class="calendly-inline-widget" style="min-width:320px;height:580px;" data-auto-load="false">

Then, execute this code after when you want to initialize the Calendly widget:

Calendly.initInlineWidget({
 url: 'https://calendly.com/test-cei',
 parentElement: document.querySelector('.calendly-inline-widget'),
});

More documentation here: Calendly Advanced embed options

Wrapping it in an Angular component

As outlined above, in order to dynamically create a Calendly embed widget, we need two things:

  1. Create a container element that the Calendly iframe will be rendered into by the Calendly Embed API
  2. Call the Calendly Embed API

These two things combine perfectly in a Component:

import { 
    Component, 
    NgModule, 
    VERSION, 
    ElementRef,
    ViewChild
} from '@angular/core'

@Component({
  selector: 'app-calendly-widget',
  template: `
        <div #container class="calendly-inline-widget" style="min-width:320px;height:580px;" data-auto-load="false"></div>
  `
})
export class CalendlyWidgetComponent {
    @ViewChild('container') container: ElementRef;

    ngOnInit() {
      Calendly.initInlineWidget({
        url: 'https://calendly.com/test-cei',
        parentElement: this.container.nativeElement
      });
    }

The above code (TypeScript) defines a component that renders the container and immediately calls the Calendly Embed API upon initialization. We use Angular's @ViewChild to access the raw DOM element that the component renders.

Here's a working demo: https://plnkr.co/edit/mpl6l8ifxc1amS611DMD?p=preview (note that it uses an older version of Angular than you're using, let me know if you have compatibility issues)

Dmitry Pashkevich
  • 13,431
  • 9
  • 55
  • 73
  • Thank you for your help. I've only had a couple of minutes to tinker with this, and I'm pretty new to Angular and JavaScript. So, I have tried putting the second bunch of code in script tags in index.html and in my Component template, and I also tried coding it into ngOnInit in my component. Neither seemed to work. I'm unfamiliar with how to add regular Javascript to an Angular project. Any advice you could offer would be appreciated. – wingej0 May 04 '19 at 13:51
  • I have added it to the OP. I tried some other things, but none of them worked or seemed particularly logical. Ideally, I would add the script to the component.ts file, but I have no idea how to do that or if it is even possible. Thanks again. This seems like it should be simple, but it's been a major headache. – wingej0 May 05 '19 at 14:11
  • 3
    It anyone is still having issues due strong typing on not finding Calendly object, just put export {}; declare global { interface Window { Calendly: any; } } on globals.ts – Camilo Casadiego Sep 11 '20 at 01:35