Creating Components with Third-Party Libraries
Learn how to create self-contained, reusable custom components that integrate third-party JavaScript libraries like FullCalendar, Leaflet maps, Chart.js, and more.
Overview
BetterForms custom components can integrate any JavaScript library using lifecycle hooks. This guide shows you how to:
β Load external libraries on-demand
β Initialize libraries with DOM elements
β Properly clean up when components are removed
β Create fully self-contained, shareable components
Prerequisites
Basic understanding of JSON
Familiarity with the BetterForms Component Editor
Knowledge of the third-party library you want to integrate
Component Lifecycle Hooks
Custom components support lifecycle hooks for managing loading, initialization, and cleanup:
Available Hooks
onBeforeMount
Before component renders (blocks rendering)
Loading external libraries, fetching data
onMount
After component renders to DOM
Initializing libraries, accessing DOM elements
onUpdated
After component data changes
Updating library instances
onBeforeDestroy
Before component is removed
Cleanup, destroying library instances
onDestroyed
After component is removed
Final cleanup
Execution Order
Complete Example: FullCalendar Component
This example demonstrates all key patterns for integrating a third-party library.
Step 1: Component Structure
Step 2: Load the Library (onBeforeMount)
Why onBeforeMount?
Component waits for library to load before rendering
Prevents "FullCalendar is not defined" errors
BF.libraryLoadOnce()deduplicates - safe to use in multiple components
Step 3: Initialize the Library (onMount)
Key Patterns:
Access DOM with
document.getElementById()Always check if element exists
Store API reference globally
Access model data
Step 4: Add Cleanup (onBeforeDestroy)
Why cleanup is important:
Prevents memory leaks
Stops event listeners
Clears intervals/timeouts
Frees resources
Step 5: Add Custom Actions (Optional)
This action can be called from buttons or other components:
Complete Working Component
Here's the full JSON you can copy and use:
Using the Component on a Page
Add to your page schema:
Providing Event Data
Set model.calendarEvents in your page data model:
Adding Navigation Buttons
Common Patterns
Pattern 1: Simple Library (No DOM Access)
For libraries that don't need DOM elements (like Lodash, Moment.js):
Pattern 2: Library Needing DOM Access
For libraries that render to a DOM element (FullCalendar, Chart.js, Leaflet):
Pattern 3: Singleton Initialization
When registering Vue components or global objects (only initialize once):
Important: DOM Access in namedActions
β What DOESN'T Work
β
What DOES Work
Best Practice: Use id Attributes
id AttributesAlways add id attributes to elements you need to access in lifecycle hooks:
Another Example: Chart.js Component
Finding CDN URLs for Libraries
Most JavaScript libraries provide CDN links. Here are common sources:
Option 1: jsDelivr (Recommended)
Search for your library and get the CDN URL:
Option 2: Library's Official Docs
Most libraries document their CDN links:
FullCalendar: https://fullcalendar.io/docs/initialize-globals
Leaflet: https://leafletjs.com/download.html
Loading CSS Stylesheets
Some libraries require CSS files:
Troubleshooting
Issue: "Element not found" in onMount
Symptoms:
Console error: "Element not found"
Library fails to initialize
Blank component
Solutions:
Verify the
idin HTML matches thegetElementById()callCheck console for JavaScript errors
Ensure the element has content/dimensions (add
style="min-height: 500px;")
Issue: Library is not defined
Symptoms:
"ReferenceError: FullCalendar is not defined"
Solutions:
Verify CDN URL is correct
Check that
onBeforeMountis loading the libraryCheck browser Network tab - is the script loading?
Try a different CDN or version
Issue: Component works but memory leak
Symptoms:
Multiple instances stack up
Performance degrades over time
Solutions:
Add
onBeforeDestroycleanupCall library's destroy/remove method
Clear global references (
window._api = null)
Issue: "this.$refs is not a function"
Symptoms:
TypeError about $refs
Solution:
You cannot use
this.$refsin namedAction functionsUse
document.getElementById()instead
Issue: "schema is not defined"
Symptoms:
ReferenceError: schema is not defined
Solution:
schemais not accessible in namedAction functionsStore configuration in
modelor hardcode in the functionAccess via
model.myConfiginstead
Best Practices
β
DO:
Use
idattributes for elements you need to accessCheck if elements exist before using them
Store library instances in
windowfor global accessAdd cleanup in
onBeforeDestroyUse
modelfor dynamic dataLog to console for debugging
Test with mock data first
β DON'T:
Use
this.$refsin namedActions (not available)Access
schemadirectly in functions (not available)Forget to destroy library instances
Load libraries globally if components are self-contained
Use synchronous operations that block rendering
More Examples
Leaflet Maps
CodeMirror Editor
Quick Reference Checklist
When creating a component with a third-party library:
See Also
Web Awesome Components - Modern web components integration
BF.libraryLoadOnce() Reference - Library loading utility
Named Actions - Understanding named actions
Component Editor - Using the component editor UI
Next Steps
Copy one of the complete examples above
Modify the HTML, configuration, and actions for your needs
Test in the component editor with mock data
Add to your component library
Use on pages across your app
You now have everything needed to integrate any JavaScript library into BetterForms! π
Last updated