Skip to content

Instantly share code, notes, and snippets.

@rcline
Forked from dimfeld/svelte-shim.ts
Last active December 5, 2020 12:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rcline/af3a58cd5324dfcd5e7e22e7f3c64347 to your computer and use it in GitHub Desktop.
Save rcline/af3a58cd5324dfcd5e7e22e7f3c64347 to your computer and use it in GitHub Desktop.
Turn a Svelte component into an AngularJS component
import type { SvelteComponent } from "svelte";
import type { IControllerConstructor, IOnChangesObject } from "angular";
/**
* Turn a Svelte component into an AngularJS component
*
* ## Usage
*
* Create the component boilerplate for use inside AngularJS code:
// app.header.component.ts
import type { IComponentOptions } from 'angular';
import svelteShim from '../utils/svelte-shim';
import AppHeader from './AppHeader.svelte';
const AppHeaderComponent: IComponentOptions = {
controller: svelteShim(
AppHeader,
{}
),
bindings: {}
};
export default AppHeaderComponent;
*
* Attach the component to the angular app:
// app.header.module.ts
import angular from 'angular';
import AppHeaderComponent from './app.header.component';
angular.module('Crops')
.component('appHeader', AppHeaderComponent);
*
* Use the component in AngularJS code:
<page-header count="count" header-mode="mode"></page-header>
*
* @param Component
* @param events
* @returns {IComponentOptions}
*/
export default function (
Component: typeof SvelteComponent,
events?: { [svelteEvent: string]: string }
): IControllerConstructor {
return class {
$element: Element[];
initialProps: { [key: string]: unknown; } = {};
component: SvelteComponent | undefined;
constructor($element: Element[]) {
'ngInject';
this.$element = $element;
}
addInitialProps(extraProps: { [key: string]: unknown; }) {
this.initialProps = {
...this.initialProps,
...extraProps,
};
}
$postLink() {
this.component = new Component({
target: this.$element[0],
props: this.initialProps,
});
if (events) {
Object.keys(events).forEach(svelteEvent => {
const angularBinding = events[svelteEvent];
if (this.component) {
this.component.$on(svelteEvent, ({detail}) => {
(this as unknown as any)[angularBinding](detail); // eslint-disable-line @typescript-eslint/no-explicit-any
});
}
}, this);
}
}
$onChanges(changes: IOnChangesObject) {
const changed: { [key: string]: unknown; } = {};
Object.keys(changes).forEach(key => {
changed[key] = changes[key].currentValue;
});
if (this.component) {
this.component.$set(changed);
} else {
this.addInitialProps(changed);
}
}
$onDestroy() {
if (this.component) {
this.component.$destroy();
}
}
};
}
@rcline
Copy link
Author

rcline commented Oct 12, 2020

Last ES6 only (not Typescript) revision on Jun 12 2020.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment