Skip to content

Instantly share code, notes, and snippets.

@ccnokes
Last active February 19, 2019 19:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccnokes/9860591e48f05f4f8cd1ea1458e22354 to your computer and use it in GitHub Desktop.
Save ccnokes/9860591e48f05f4f8cd1ea1458e22354 to your computer and use it in GitHub Desktop.
withNgService HOC for injecting modules from Angular.JS's dependency injector into a React component
import * as React from 'react';
import hoistStatics from 'hoist-non-react-statics';
declare var angular: any;
let injector;
// NOTE you probably can't run this at the top level of a module because angular takes time to load and bootstrap
export default function getNgService<T = any>(serviceName: string): T {
if (!injector) {
injector = angular.element(document.body).injector();
// if we still don't get it, blow up
if (!injector) {
throw new Error(`Unable to get the angular injector`);
}
}
return injector.get(serviceName);
}
export const withNgService = function <NgProps = {}, ComponentProps = {}>(...injectorKeys: string[]) {
return function<Props = ComponentProps>(Component: React.ComponentType<Props & NgProps>): React.ComponentType<Props> {
class withNgServiceWrapper extends React.Component<Props & NgProps> {
static displayName = `withNgService(${Component.displayName || Component.name})`;
static WrappedComponent = Component;
private ngProps = injectorKeys.reduce((aggr, key) => {
aggr[key] = getNgService(key);
return aggr;
}, {} as NgProps);
render() {
return (
<Component
{...this.props}
{...this.ngProps}
/>
);
}
}
return hoistStatics(withNgServiceWrapper, Component);
}
}
// test it out
interface MyNgProps {
ngThing: string
}
interface Props {
a: number
}
class _Test extends React.Component<Props & MyNgProps> {
render() {
const { a, ngThing } = this.props
return null
}
}
const Test = withNgService<MyNgProps>('$http')(_Test)
const Test2 = withNgService<MyNgProps, Props>('$http')((props) => (
<p>{props.ngThing}{props.a}</p>
))
class App extends React.Component {
render() {
return (
<>
<Test a={1} />
<Test2 a={123} />
</>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment