Introduction
If youâre an Angular dev eyeing the React world, you might feel like a cat walking into a dog park. tldraw
âthe cool kid on the React blockâmakes it seem worth the risk. But how do you get them to play nicely together? By using web components, the ultimate middleman that lets Angular and React shake hands instead of throwing shade. đ
What are Web Components?
Imagine a magical HTML element that doesnât care who made itâit just works. Thatâs a web component for you! It's like the Switzerland of the web frameworks, neutral and ready to mediate.
Key Features:
-
Custom Elements: Make up your own tags like
<awesome-button>
. - Shadow DOM: Keeps your styles from messing with everyone elseâs (no sibling drama here!).
- HTML Templates: Build it once, reuse it everywhere (yes, like Legos).
What is r2wc?
Think of r2wc
as the translator between React and the rest of the web. It wraps your React components in a cozy custom element that even Angular can understand. đ
How it Works:
- Take your React component. đ§âđ¨
- Wrap it with
r2wc
. đ - Register it as a custom element with a snazzy name like
<tl-draw>
. đˇď¸
Step-by-Step Guide
Step 1: Install the Required Stuff
Get the cool toys with:
npm install @r2wc/react-to-web-component @tldraw/tldraw react react-dom
Step 2: Let Angular Know About Web Components
Add this to your Angular module, so Angular doesnât freak out about your new custom elements:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent],
})
export class AppModule {}
Step 3: Add tldraw Styles
You canât draw without style, right? Add tldraw
's styles to your Angular app.
Open angular.json
and include the following in the styles array:
"styles": [
"src/global.scss",
"node_modules/tldraw/tldraw.css"
]
Step 4: Importing tldraw Based on Angular Version
- For Angular 15 and Above:
import r2wc from "@r2wc/react-to-web-component";
import { Tldraw, getSnapshot } from "@tldraw/tldraw";
- For Angular Below 15:
import r2wc from "../../node_modules/@r2wc/react-to-web-component/dist/react-to-web-component.js";
import { Tldraw, getSnapshot } from "../../node_modules/tldraw/dist-esm/index.mjs";
Because Angularâs TypeScript isnât quite ready to hang with tldraw. đ. This workaround is necessary because tldraw uses TypeScript features that older Angular versions donât fully support.
Step 5: Create tldraw.js
Create a file named tldraw.js
to convert the tldraw
React component into a web component.
Hereâs the magic potion that converts tldraw into a web component:
import r2wc from "@r2wc/react-to-web-component";
import { Tldraw, getSnapshot } from "@tldraw/tldraw";
const TldrawComponent = r2wc(Tldraw, {
props: {
forceMobile: "boolean",
snapshot: "json",
onMount: "function",
},
});
customElements.define("tl-draw", TldrawComponent);
export const getSnapshot1 = getSnapshot;
This wraps the tldraw component and defines it as a custom element named .
Step 6: Use the Web Component in Angular
Hereâs how you can use <tl-draw>
in your Angular app.
HTML (app.component.html
):
<div style="width: 100vw; height: 95vh">
<button
(click)="handleSaveChanges()"
[ngStyle]="{
position: 'absolute',
top: '44px',
right: '0.5em',
padding: '8px 16px',
zIndex: 100,
backgroundColor: hasUnsavedChanges ? '#007bff' : '#ccc',
cursor: hasUnsavedChanges ? 'pointer' : 'not-allowed',
opacity: hasUnsavedChanges ? 1 : 0.6
}"
>
Save
</button>
<tl-draw
[forceMobile]="true"
[snapshot]="snapshot"
[onMount]="onMountEvent"
></tl-draw>
</div>
TypeScript (app.component.ts):
import { Component, OnInit } from '@angular/core';
import { getSnapshot1 } from './path-to-tldraw.js';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
hasUnsavedChanges = false;
snapshot: any;
editor: any;
onMountEvent = (editor: any) => {
this.editor = editor;
editor.store.listen(this.handleChangeEvent, { source: 'user', scope: 'all' });
};
handleChangeEvent = (change: any) => {
if (
Object.keys(change.changes.added).length ||
Object.keys(change.changes.updated).length ||
Object.keys(change.changes.removed).length
) {
this.hasUnsavedChanges = true;
}
};
handleSaveChanges = () => {
const snapshot = getSnapshot1(this.editor.store);
console.log('Snapshot saved:', snapshot);
this.hasUnsavedChanges = false;
localStorage.setItem('drawingSnapshot', JSON.stringify(snapshot));
};
ngOnInit() {
const savedSnapshot = localStorage.getItem('drawingSnapshot');
this.snapshot = savedSnapshot ? JSON.parse(savedSnapshot) : {};
}
}
Now, youâre all set to use tldraw in your Angular app! đ
Key Takeaways
-
Props Mapping: React props become Angular-friendly attributes via
r2wc
. For example:
<tl-draw
[forceMobile]="true"
[snapshot]="snapshot"
[onMount]="onMountEvent"
></tl-draw>
- Event Handling: Use Angular bindings to handle events like [onMount]="onMountEvent".
- Snapshots FTW: Save and restore drawing state using getSnapshot.
Youâve successfully bridged the React-Angular divide! đ
Common Gotchas
TypeScript Compatibility: If you see errors, try downgrading TypeScript to a compatible version.
Missing Styles: If your canvas looks broken, check
angular.json
to ensuretldraw.css
is added to the styles array.Prop Mismatches: Double-check the
props
object intldraw.js
to make sure attributes likeforceMobile
are correctly exposed.
Conclusion
By the time youâre done, your Angular app will be flexing tldraw like it was born to do it. Who said React and Angular canât get along? With a little help from r2wc
, youâve just made it happen. Go on, give yourself a high five! đď¸đ
Top comments (0)