Skip to content

Commit 2b7656b

Browse files
authored
feat: support function as options.template (#568)
Allow `template` to accept a function `(props: AppProps) => string` in addition to a plain string. This enables dynamic template generation based on single-spa props at mount time. - Update `BaseSingleSpaAngularOptions` type to accept `string | ((props: AppProps) => string)` - Call the function with `props` in `getContainerElementAndSetTemplate` if `template` is a function - Update validation error message in `singleSpaAngular` to reflect both accepted types - Update navbar example app to use the new function form
1 parent cd76857 commit 2b7656b

4 files changed

Lines changed: 9 additions & 5 deletions

File tree

apps/navbar/src/main.single-spa.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const lifecycles = singleSpaAngular({
1010
const platformRef = platformBrowser(provideSingleSpaPlatform());
1111
return bootstrapApplication(AppComponent, appConfig, { platformRef });
1212
},
13-
template: '<navbar-root />',
13+
template: () => '<navbar-root />',
1414
NgZone: 'noop',
1515
Router,
1616
NavigationStart,

libs/single-spa-community-angular/internals/src/dom.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ export function getContainerElementAndSetTemplate<T extends BaseSingleSpaAngular
1414
);
1515
}
1616

17+
// If the template is a function, we call it with the props to get the string template.
18+
const template =
19+
typeof options.template === 'function' ? options.template(props) : options.template;
20+
1721
const containerElement = getContainerElement(domElementGetter, props);
18-
containerElement.innerHTML = options.template;
22+
containerElement.innerHTML = template;
1923
return containerElement;
2024
}
2125

libs/single-spa-community-angular/internals/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ApplicationRef, NgModuleRef } from '@angular/core';
44
export type DomElementGetter = (props: any) => HTMLElement;
55

66
export interface BaseSingleSpaAngularOptions {
7-
template: string;
7+
template: string | ((props: AppProps) => string);
88
domElementGetter?: DomElementGetter;
99
bootstrapFunction(props: AppProps): Promise<NgModuleRef<any> | ApplicationRef>;
1010
}

libs/single-spa-community-angular/src/single-spa-angular.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ export function singleSpaAngular<T>(userOptions: SingleSpaAngularOptions<T>): Li
3131
throw Error('single-spa-angular must be passed an options.bootstrapFunction');
3232
}
3333

34-
if (typeof options.template !== 'string') {
35-
throw Error('single-spa-angular must be passed options.template string');
34+
if (typeof options.template !== 'string' && typeof options.template !== 'function') {
35+
throw Error('single-spa-angular must be passed options.template string or function');
3636
}
3737

3838
if (!options.NgZone) {

0 commit comments

Comments
 (0)