-
-
Save rcline/af3a58cd5324dfcd5e7e22e7f3c64347 to your computer and use it in GitHub Desktop.
Turn a Svelte component into an AngularJS component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Last ES6 only (not Typescript) revision on Jun 12 2020.