UNPKG

single-spa-angularjs

Version:

the logic needed to register angular 1 apps with single-spa

197 lines (166 loc) 5.34 kB
const defaultOpts = { // required opts angular: null, domElementGetter: null, mainAngularModule: null, // optional opts uiRouter: false, ngRoute: false, preserveGlobal: false, elementId: "__single_spa_angular_1", strictDi: false, template: undefined, }; export default function singleSpaAngularJS(userOpts) { if (typeof userOpts !== "object") { throw new Error(`single-spa-angularjs requires a configuration object`); } const opts = { ...defaultOpts, ...userOpts, }; if (!opts.angular) { throw new Error(`single-spa-angularjs must be passed opts.angular`); } if (!opts.mainAngularModule) { throw new Error( `single-spa-angularjs must be passed opts.mainAngularModule string` ); } // A shared object to store mounted object state const mountedInstances = {}; return { bootstrap: bootstrap.bind(null, opts, mountedInstances), mount: mount.bind(null, opts, mountedInstances), unmount: unmount.bind(null, opts, mountedInstances), }; } function bootstrap(opts, mountedInstances, singleSpaProps) { return Promise.resolve().then(() => { let module; try { module = opts.angular.module("single-spa-angularjs"); } catch (err) { // ignore - this means that the module doesn't exist } if (module) { module.config([ "$provide", ($provide) => { $provide.value("singleSpaProps", singleSpaProps); }, ]); } }); } function mount(opts, mountedInstances, props = {}) { return Promise.resolve().then(() => { window.angular = opts.angular; const domElementGetter = chooseDomElementGetter(opts, props); const domElement = getRootDomEl(domElementGetter, props); const bootstrapEl = document.createElement("div"); bootstrapEl.id = opts.elementId; domElement.appendChild(bootstrapEl); if (opts.uiRouter) { const uiViewEl = document.createElement("div"); uiViewEl.setAttribute( "ui-view", opts.uiRouter === true ? "" : opts.uiRouter ); bootstrapEl.appendChild(uiViewEl); } if(opts.ngRoute){ const ngViewEl = document.createElement("div"); ngViewEl.setAttribute( "ng-view","" ); bootstrapEl.appendChild(ngViewEl); } if (opts.template) { bootstrapEl.innerHTML = opts.template; } if (opts.strictDi) { mountedInstances.instance = opts.angular.bootstrap( bootstrapEl, [opts.mainAngularModule], { strictDi: opts.strictDi } ); } else { mountedInstances.instance = opts.angular.bootstrap(bootstrapEl, [ opts.mainAngularModule, ]); } mountedInstances.instance.get("$rootScope").singleSpaProps = props; // https://github.com/single-spa/single-spa-angularjs/issues/51 mountedInstances.instance.get("$rootScope").$apply(); }); } function unmount(opts, mountedInstances, props = {}) { return new Promise((resolve, reject) => { if (mountedInstances.instance.has("$uiRouter")) { // https://github.com/single-spa/single-spa-angularjs/issues/53 const uiRouter = mountedInstances.instance.get("$uiRouter"); if (uiRouter.dispose) { uiRouter.dispose(); } else { console.warn( "single-spa-angularjs: the uiRouter instance doesn't have a dispose method and so it will not be properly unmounted." ); } } mountedInstances.instance.get("$rootScope").$destroy(); const domElementGetter = chooseDomElementGetter(opts, props); const domElement = getRootDomEl(domElementGetter, props); domElement.innerHTML = ""; if (opts.angular === window.angular && !opts.preserveGlobal) delete window.angular; setTimeout(resolve); }); } function chooseDomElementGetter(opts, props) { if (props.domElement) { return () => props.domElement; } else if (props.domElementGetter) { return props.domElementGetter; } else if (opts.domElementGetter) { return opts.domElementGetter; } else { return defaultDomElementGetter(props); } } function defaultDomElementGetter(props) { const appName = props.appName || props.name; if (!appName) { throw Error( `single-spa-angularjs was not given an application name as a prop, so it can't make a unique dom element container for the angularjs application` ); } const htmlId = `single-spa-application:${appName}`; return function defaultDomEl() { let domElement = document.getElementById(htmlId); if (!domElement) { domElement = document.createElement("div"); domElement.id = htmlId; document.body.appendChild(domElement); } return domElement; }; } function getRootDomEl(domElementGetter, props) { if (typeof domElementGetter !== "function") { throw new Error( `single-spa-angularjs: the domElementGetter for angularjs application '${ props.appName || props.name }' is not a function` ); } const element = domElementGetter(props); if (!element) { throw new Error( `single-spa-angularjs: domElementGetter function for application '${ props.appName || props.name }' did not return a valid dom element. Please pass a valid domElement or domElementGetter via opts or props` ); } return element; }