npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

angular-calendly

v1.0.0

Published

Angular library for integrating Calendly scheduling widgets

Downloads

21

Readme

Angular Calendly

Seamlessly integrate Calendly scheduling widgets into your Angular applications

npm version MIT License Angular

A modern Angular library that provides standalone components for embedding Calendly scheduling widgets. Built with TypeScript, fully typed, and compatible with Angular 18+.

Table of Contents

Features

Modern Angular - Standalone components compatible with Angular 18, 19, and 20

📱 Multiple Widget Types - Inline and Popup widgets for different use cases

🎨 Highly Customizable - Colors, prefill data, UTM parameters, and more

📊 Event Tracking - Built-in callbacks for user interactions

🔧 TypeScript First - Fully typed with comprehensive type definitions

🌐 SSR Compatible - Works seamlessly with Angular Universal

Zero Configuration - Automatic script loading and management

🪶 Lightweight - Minimal bundle impact with tree-shakable exports

Installation

Install via npm:

npm install angular-calendly

Or using yarn:

yarn add angular-calendly

Or using pnpm:

pnpm add angular-calendly

Quick Start

1. Import the Component

import { Component } from '@angular/core';
import { CalendlyInlineComponent } from 'angular-calendly';

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline
      [url]="'https://calendly.com/your-username/30min'"
    ></ng-calendly-inline>
  `
})
export class BookingComponent {}

2. That's it!

The component automatically loads the Calendly SDK and renders the widget. No additional configuration needed.

Usage

Inline Widget

Embed Calendly directly into your page for a seamless booking experience.

Basic Example:

import { Component } from '@angular/core';
import { CalendlyInlineComponent } from 'angular-calendly';

@Component({
  selector: 'app-scheduling',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline
      [url]="calendlyUrl"
      [height]="700"
    ></ng-calendly-inline>
  `
})
export class SchedulingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';
}

With Prefill Data:

import { Component } from '@angular/core';
import { CalendlyInlineComponent, CalendlyPrefill } from 'angular-calendly';

@Component({
  selector: 'app-scheduling',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline
      [url]="calendlyUrl"
      [prefill]="prefillData"
      [height]="700"
    ></ng-calendly-inline>
  `
})
export class SchedulingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';

  prefillData: CalendlyPrefill = {
    name: 'John Doe',
    email: '[email protected]',
    firstName: 'John',
    lastName: 'Doe'
  };
}

With Event Tracking:

import { Component } from '@angular/core';
import { CalendlyInlineComponent, CalendlyEvent } from 'angular-calendly';

@Component({
  selector: 'app-scheduling',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline
      [url]="calendlyUrl"
      (eventScheduled)="onEventScheduled($event)"
      (dateAndTimeSelected)="onDateSelected($event)"
    ></ng-calendly-inline>
  `
})
export class SchedulingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';

  onEventScheduled(event: CalendlyEvent) {
    console.log('Meeting scheduled!', event);
    // Send to analytics, show confirmation, etc.
  }

  onDateSelected(event: CalendlyEvent) {
    console.log('Date selected:', event);
  }
}

Popup Widget

Open Calendly in a modal overlay with a customizable trigger button.

Basic Example:

import { Component } from '@angular/core';
import { CalendlyPopupComponent } from 'angular-calendly';

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyPopupComponent],
  template: `
    <ng-calendly-popup
      [url]="calendlyUrl"
      [buttonText]="'Schedule a meeting'"
    ></ng-calendly-popup>
  `
})
export class BookingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';
}

Custom Button Styling:

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyPopupComponent],
  template: `
    <ng-calendly-popup
      [url]="calendlyUrl"
      [buttonClass]="'btn btn-primary btn-lg'"
      [buttonText]="'Book Your Appointment'"
    ></ng-calendly-popup>
  `,
  styles: [`
    .btn {
      padding: 12px 24px;
      border: none;
      border-radius: 8px;
      font-size: 16px;
      cursor: pointer;
    }
    .btn-primary {
      background: #0066ff;
      color: white;
    }
    .btn-primary:hover {
      background: #0052cc;
    }
  `]
})
export class BookingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';
}

Custom Content:

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyPopupComponent],
  template: `
    <ng-calendly-popup [url]="calendlyUrl">
      <div class="custom-button">
        <span class="icon">📅</span>
        <span>Schedule Now</span>
      </div>
    </ng-calendly-popup>
  `
})
export class BookingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';
}

Programmatic Control

Control the popup widget programmatically using component references or utility functions.

Using ViewChild:

import { Component, ViewChild } from '@angular/core';
import { CalendlyPopupComponent } from 'angular-calendly';

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyPopupComponent],
  template: `
    <ng-calendly-popup
      [url]="calendlyUrl"
      [hideButton]="true"
      #calendlyPopup
    ></ng-calendly-popup>

    <button (click)="openBooking()">Book a Meeting</button>
    <button (click)="closeBooking()">Cancel</button>
  `
})
export class BookingComponent {
  @ViewChild('calendlyPopup') calendlyPopup!: CalendlyPopupComponent;
  calendlyUrl = 'https://calendly.com/your-username/30min';

  openBooking() {
    this.calendlyPopup.openPopup();
  }

  closeBooking() {
    this.calendlyPopup.closePopup();
  }
}

Using Utility Functions:

import { Component } from '@angular/core';
import { openCalendlyPopup, closeCalendlyPopup } from 'angular-calendly';

@Component({
  selector: 'app-booking',
  standalone: true,
  template: `
    <button (click)="openBooking()">Book a Meeting</button>
  `
})
export class BookingComponent {
  openBooking() {
    openCalendlyPopup('https://calendly.com/your-username/30min');
  }

  closeBooking() {
    closeCalendlyPopup();
  }
}

API Reference

CalendlyInlineComponent

Embeds Calendly directly in your page.

Inputs

| Property | Type | Required | Default | Description | |----------|------|----------|---------|-------------| | url | string | ✅ Yes | - | Your Calendly scheduling page URL | | prefill | CalendlyPrefill | No | undefined | Prefill user information | | utm | CalendlyUtm | No | undefined | UTM parameters for tracking | | backgroundColor | string | No | undefined | Background color (hex without #) | | textColor | string | No | undefined | Text color (hex without #) | | primaryColor | string | No | undefined | Primary/accent color (hex without #) | | hideEventTypeDetails | boolean | No | false | Hide event type details | | hideLandingPageDetails | boolean | No | false | Hide landing page details | | hideGdprBanner | boolean | No | false | Hide GDPR consent banner | | height | number | No | 700 | Widget height in pixels | | minWidth | number | No | 320 | Minimum width in pixels |

Outputs

| Event | Type | Description | |-------|------|-------------| | profilePageViewed | EventEmitter<CalendlyEvent> | Fired when the profile page is viewed | | eventTypeViewed | EventEmitter<CalendlyEvent> | Fired when an event type page is viewed | | dateAndTimeSelected | EventEmitter<CalendlyEvent> | Fired when a date and time are selected | | eventScheduled | EventEmitter<CalendlyEvent> | Fired when an event is successfully scheduled |

CalendlyPopupComponent

Opens Calendly in a modal overlay.

Inputs

| Property | Type | Required | Default | Description | |----------|------|----------|---------|-------------| | url | string | ✅ Yes | - | Your Calendly scheduling page URL | | prefill | CalendlyPrefill | No | undefined | Prefill user information | | utm | CalendlyUtm | No | undefined | UTM parameters for tracking | | backgroundColor | string | No | undefined | Background color (hex without #) | | textColor | string | No | undefined | Text color (hex without #) | | primaryColor | string | No | undefined | Primary/accent color (hex without #) | | hideEventTypeDetails | boolean | No | false | Hide event type details | | hideLandingPageDetails | boolean | No | false | Hide landing page details | | hideGdprBanner | boolean | No | false | Hide GDPR consent banner | | buttonText | string | No | 'Schedule time with me' | Text for the trigger button | | buttonClass | string | No | undefined | CSS class(es) for the button | | buttonStyle | string | No | undefined | Inline styles for the button | | hideButton | boolean | No | false | Hide the default button (for programmatic use) | | autoOpen | boolean | No | false | Automatically open on component init |

Outputs

| Event | Type | Description | |-------|------|-------------| | profilePageViewed | EventEmitter<CalendlyEvent> | Fired when the profile page is viewed | | eventTypeViewed | EventEmitter<CalendlyEvent> | Fired when an event type page is viewed | | dateAndTimeSelected | EventEmitter<CalendlyEvent> | Fired when a date and time are selected | | eventScheduled | EventEmitter<CalendlyEvent> | Fired when an event is successfully scheduled | | popupClosed | EventEmitter<void> | Fired when the popup is closed |

Methods

| Method | Returns | Description | |--------|---------|-------------| | openPopup() | void | Programmatically open the popup | | closePopup() | void | Programmatically close the popup |

TypeScript Interfaces

CalendlyPrefill

interface CalendlyPrefill {
  name?: string;              // Full name
  email?: string;             // Email address
  firstName?: string;         // First name
  lastName?: string;          // Last name
  customAnswers?: Record<string, string>; // Custom question answers
  guests?: string[];          // Guest email addresses
  date?: Date;               // Pre-selected date
}

CalendlyUtm

interface CalendlyUtm {
  utmCampaign?: string;      // Campaign name
  utmSource?: string;        // Traffic source
  utmMedium?: string;        // Marketing medium
  utmContent?: string;       // Ad content
  utmTerm?: string;          // Search term
}

CalendlyEvent

interface CalendlyEvent {
  event: string;
  payload?: {
    event?: {
      uri?: string;
    };
    invitee?: {
      uri?: string;
    };
  };
}

Utility Functions

openCalendlyPopup()

function openCalendlyPopup(url: string): void

Opens a Calendly popup with the specified URL.

closeCalendlyPopup()

function closeCalendlyPopup(): void

Closes any open Calendly popup.

isCalendlyEvent()

function isCalendlyEvent(event: MessageEvent): boolean

Checks if a message event originated from Calendly.

Example:

window.addEventListener('message', (e) => {
  if (isCalendlyEvent(e)) {
    console.log('Calendly event received:', e.data);
  }
});

Advanced Usage

Custom Styling

Customize the widget appearance to match your brand:

<ng-calendly-inline
  [url]="calendlyUrl"
  [primaryColor]="'0066ff'"
  [backgroundColor]="'ffffff'"
  [textColor]="'333333'"
></ng-calendly-inline>

Note: Provide hex colors without the # symbol.

UTM Tracking

Track campaign performance by adding UTM parameters:

import { CalendlyUtm } from 'angular-calendly';

utmParams: CalendlyUtm = {
  utmCampaign: 'spring_sale_2024',
  utmSource: 'website',
  utmMedium: 'banner',
  utmContent: 'hero_section',
  utmTerm: 'book_now'
};

// In template
<ng-calendly-inline
  [url]="calendlyUrl"
  [utm]="utmParams"
></ng-calendly-inline>

Custom Answers

Pre-fill custom question answers:

prefillData: CalendlyPrefill = {
  name: 'John Doe',
  email: '[email protected]',
  customAnswers: {
    'a1': 'Enterprise Plan',
    'a2': 'Referral'
  }
};

Complete Example

A fully configured widget with all features:

import { Component } from '@angular/core';
import {
  CalendlyInlineComponent,
  CalendlyPrefill,
  CalendlyUtm,
  CalendlyEvent
} from 'angular-calendly';

@Component({
  selector: 'app-advanced-scheduling',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <div class="scheduling-container">
      <h2>Book Your Consultation</h2>
      <ng-calendly-inline
        [url]="calendlyUrl"
        [height]="800"
        [prefill]="prefillData"
        [utm]="utmParams"
        [primaryColor]="'0066ff'"
        [hideGdprBanner]="true"
        (profilePageViewed)="onProfileViewed()"
        (eventTypeViewed)="onEventTypeViewed()"
        (dateAndTimeSelected)="onDateSelected($event)"
        (eventScheduled)="onEventScheduled($event)"
      ></ng-calendly-inline>
    </div>
  `,
  styles: [`
    .scheduling-container {
      max-width: 1000px;
      margin: 0 auto;
      padding: 2rem;
    }
  `]
})
export class AdvancedSchedulingComponent {
  calendlyUrl = 'https://calendly.com/your-username/consultation';

  prefillData: CalendlyPrefill = {
    name: 'Jane Smith',
    email: '[email protected]',
    customAnswers: {
      'a1': 'Premium Plan'
    }
  };

  utmParams: CalendlyUtm = {
    utmCampaign: 'website_2024',
    utmSource: 'organic',
    utmMedium: 'web'
  };

  onProfileViewed() {
    console.log('User viewing profile');
  }

  onEventTypeViewed() {
    console.log('User viewing event types');
  }

  onDateSelected(event: CalendlyEvent) {
    console.log('Date selected:', event);
    // Track in analytics
  }

  onEventScheduled(event: CalendlyEvent) {
    console.log('Event scheduled:', event);
    // Show success message
    // Send confirmation email
    // Update database
  }
}

Examples

Integration with Module-based Apps

If you're using NgModules instead of standalone components:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CalendlyInlineComponent, CalendlyPopupComponent } from 'angular-calendly';

@NgModule({
  imports: [
    BrowserModule,
    CalendlyInlineComponent,  // Import as module
    CalendlyPopupComponent
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

Responsive Height

Adjust widget height based on screen size:

import { Component, HostListener } from '@angular/core';
import { CalendlyInlineComponent } from 'angular-calendly';

@Component({
  selector: 'app-responsive-scheduling',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline
      [url]="calendlyUrl"
      [height]="widgetHeight"
    ></ng-calendly-inline>
  `
})
export class ResponsiveSchedulingComponent {
  calendlyUrl = 'https://calendly.com/your-username/30min';
  widgetHeight = 700;

  @HostListener('window:resize', ['$event'])
  onResize() {
    this.widgetHeight = window.innerWidth < 768 ? 600 : 800;
  }

  ngOnInit() {
    this.onResize();
  }
}

SSR Support

This library fully supports Server-Side Rendering (Angular Universal). The components automatically detect the platform and only load Calendly scripts in the browser environment.

No additional configuration needed!

// Works out of the box with Angular Universal
import { CalendlyInlineComponent } from 'angular-calendly';

@Component({
  selector: 'app-booking',
  standalone: true,
  imports: [CalendlyInlineComponent],
  template: `
    <ng-calendly-inline [url]="url"></ng-calendly-inline>
  `
})
export class BookingComponent {
  url = 'https://calendly.com/your-username/30min';
}

Troubleshooting

Widget Not Appearing

Problem: The widget doesn't show up on the page.

Solutions:

  1. Verify your Calendly URL is correct and publicly accessible
  2. Check browser console for errors
  3. Ensure you have an internet connection (widget loads external scripts)
  4. Wait a moment - the script loads asynchronously

TypeScript Errors

Problem: TypeScript compilation errors.

Solution: Make sure you're using Angular 18+ and TypeScript 5+:

npm list @angular/core typescript

Events Not Firing

Problem: Event callbacks aren't being called.

Solution: Ensure you're using the correct event names and syntax:

// ✅ Correct
(eventScheduled)="onEventScheduled($event)"

// ❌ Incorrect
(onEventScheduled)="onEventScheduled($event)"

Colors Not Applying

Problem: Custom colors aren't showing.

Solution: Provide hex colors without the # symbol:

// ✅ Correct
[primaryColor]="'0066ff'"

// ❌ Incorrect
[primaryColor]="'#0066ff'"

SSR Errors

Problem: Errors during server-side rendering.

Solution: The library handles SSR automatically. If you see window/document errors, ensure you're not accessing browser APIs directly in your component initialization.

Requirements

  • Angular: 18.0.0 or higher
  • TypeScript: 5.0.0 or higher
  • Node.js: 18.0.0 or higher (for development)

Browser Support

  • ✅ Chrome (latest)
  • ✅ Firefox (latest)
  • ✅ Safari (latest)
  • ✅ Edge (latest)
  • ✅ Mobile browsers (iOS Safari, Chrome Mobile)

Contributing

Contributions are welcome! Here's how you can help:

  1. Report bugs - Open an issue with details
  2. Suggest features - Share your ideas
  3. Submit PRs - Fix bugs or add features
  4. Improve docs - Help others understand the library

Development Setup

# Clone the repository
git clone https://github.com/your-username/angular-calendly.git

# Install dependencies
npm install

# Build the library
npm run build

# Run demo app
npm start

License

MIT License - feel free to use this library in your projects!

Support

Acknowledgments


Made with ❤️ for the Angular community