SDK for powering content and components in Angular applications by [BloomReach Experience](https://www.bloomreach.com/en/products/experience). This library makes integrating an Angular app with BloomReach Experience a breeze. It supports both client-sid
SDK for powering content and components in Angular applications by BloomReach Experience.
This library makes integrating an Angular app with BloomReach Experience a breeze. It
supports both client-side- and server-side rendered/universal Angular apps.
BloomReach Experience allows you to use an external front-end such as Angular for
rendering while still providing a native-like authoring experience, such as integrated
preview, in-context editing, drag & drop, server-side personalization. For more
information on this approach, see A new approach to integrating SPA's with WCM: Fixing
what's wrong with headless integrations.
``bash`
npm install bloomreach-experience-ng-sdk jsonpointer path-to-regexp --save
Please note that since it's not a best practice to include 3rd party libraries with an
Angular library, the 3rd party libraries have to be installed manually as done with the
above command.
Add the SDK to the app's NgModule imports:
`typescript
import { BloomreachExperienceNgSdkModule } from 'bloomreach-experience-ng-sdk';
@NgModule({
imports: [
// ... other imports
BloomreachExperienceNgSdkModule
],
...
`
Then, add the following to an Angular component where you want BloomReach to (partly)
determine what to render:
- Import ApiUrlsService, ComponentMappingsService, InitializeSdkService, and RequestContextService;ApiUrlsService
- Add these services to the constructor of the component;
- Override default API Urls using ;ComponentMappingsService
- Set component mappings through ;RequestContextService
- Set current URL-path via ;initialize()
- Call method of InitializeSdkService;
- And add to the component template.
See the next paragraph for a description and explanation of each of the services and the
components. There's also an API section below that includes more details.
`typescript
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ApiUrlsService, ComponentMappingsService, InitializeSdkService, RequestContextService } from 'bloomreach-experience-ng-sdk';
@Component({
template: ,
})
export class MyAppClass implements OnInit {
componentMappings = {
"MyCustomComponent": MyCustomComponent
};
apiUrls = {
live: {
// override live API URL here
},
preview: {
// override preview API URL here
}
}
constructor(
private router: Router,
private apiUrlsService: ApiUrlsService,
private componentMappingsService: ComponentMappingsService,
private initializeSdkService: InitializeSdkService,
private requestContextService: RequestContextService
) {}
ngOnInit() {
this.apiUrlsService.setApiUrls(this.apiUrls);
this.componentMappingsService.setComponentMappings(this.componentMappings);
this.requestContextService.parseUrlPath(this.router.url);
this.initializeSdkService.initialize();
}
}
`
The component mappings tell the Angular app what Angular components to use for rendering
components from the Page Model API response, by mapping these to the hst:label of a CMS
catalog component. These mappings are set through the ComponentMappingsService.
The RequestContextService is used to pass the current URL so that it can fetch the Page
Model for the page that is active; and to detect whether preview is active so that
meta-data for CMS' Channel Manager functionality (e.g. in-context editing) is included in
the HTML, and consequently Channel Manager functionality is enabled.
InitializeSdkService fetches the Page Model for the current URL that is set through RequestContextService. and it initializes the CMS' Channel Manager integration.
Finally, renders the components and any content referenced
from the components in the Page Model API response. This tag/component should be placed in
the Angular app at the exact location where you want the CMS components to be outputted.
A demo project is available at Github.
Please note that in order to use the Channel Manager Integration,
you need to have an Enterprise Maven account, which is only available toBloomReach's
Enterprise customers.
The demo project can be used in combination with the Angular example app. To build and
run the example app, do the following:
`bash`
npm install
npm run start
The demo project is configured for React by default, so you will have to update the CORS
headers from http://localhost:3000 to http://localhost:4200 in
[/hst:hst/hst:hosts/dev-localhost/localhost/hst:root[@hst:responseheaders]](http://localhost:8080/cms/console/?1&path=/hst:hst/hst:hosts/dev-localhost/localhost/hst:root).
Also, make sure to change the Channel Settings in the Channel Manager, and select Angular
from the front-end renderer dropdown menu.
Custom components that are rendered through can be created BaseComponent
just as any other regular Angular component, with the requirement that it should implement
the interface that is provided by the SDK.
Additionally, all components that are rendered through should @NgModule()
be added to the 's entryComponents array, as the components are created
using the componentFactory. Otherwise you will get an error during component rendering.
The following properties are passed to the component, provided it's rendered by :configuration
- - Object component configuration. Contains the contributed models, raw
parameters and resolved parameters. Content included in the component's model is not
serialized as part of the component's configuration but in a separate content object, and
a JSON Pointer reference is used to link to the actual content object. This is done to
prevent content from being included multiple times in the API response when referenced
multiple times on a page.
`typescript
import { Component, Input, OnInit } from '@angular/core';
import { BaseComponent, getNestedObject } from 'bloomreach-experience-ng-sdk';
@Component({
selector: 'app-news-list',
templateUrl:
,
styleUrls: ['./news-list.component.css']
})
export class NewsListComponent implements BaseComponent, OnInit {
@Input() configuration: any;
items: any; constructor() { }
ngOnInit() {
this.createList();
}
createList() {
this.items = getNestedObject(this.configuration, ['models', 'pageable', 'items']);
}
}
`$3
Components that reference a single content-item (e.g. the Banner component) can use a
superclass that provides a convenient method for retrieving the corresponding content-item
based on the reference found in the component's configuration.
To use the superclass, a content component has to extend
SingleContentComponent, which
is provided by the SDK. Just as a regular custom component, the component will need to
implement the BaseComponent interface.The
SingleContentComponent provides two methods: getContent() and
getImageUrl(imageRef). See more details below.Finally, content components can use the
component for rendering
the Manage Content
Button
in preview mode in the CMS.#### Properties
-
content - Object raw content object that contains the content-item's fields and
field-values. Any references to other content-items (e.g. images) are serialized as JSON
Pointers.#### Methods
-
getContent - Object retrieves the component's referenced content-item using the
JSONPointer that is found in the component's configuration. Stores the content-item
object in the content property.
- getImageUrl(imageRef: string) - String generates fully qualified URL to an image
using the JSONPointer reference to the image.#### Example
`typescript
import { Component, OnInit } from '@angular/core';
import { BaseComponent, ImageUrlService, PageModelService, SingleContentComponent } from 'bloomreach-experience-ng-sdk';@Component({
selector: 'app-banner',
templateUrl:
,
styleUrls: ['./banner.component.css']
})
export class BannerComponent extends SingleContentComponent implements BaseComponent, OnInit {
imageUrl: string; constructor(imageUrlService: ImageUrlService, pageModelService: PageModelService) {
super(imageUrlService, pageModelService);
}
ngOnInit() {
super.ngOnInit();
this.getImage();
}
getImage() {
if (this.content && this.content.image) {
this.imageUrl = super.getImageUrl(this.content.image);
}
}
}
`$3
Static CMS components are components that are defined by developers / administrators and
cannot be modified by users in the CMS. However, any content or site menus these
components reference can be changed by users in the CMS.
Since
only renders container components (drag-and-drop components)
by default, you have to specify two additional properties in order to render a static CMS
component:
- path property to point to the relative path of the component;
- renderComponent property to specify which Angular component to use for rendering the
component. See the example below.`typescript
import { Component } from '@angular/core';
import { MenuComponent } from '../cms-components/menu/menu.component';@Component({
selector: 'app-static-component-example',
templateUrl:
,
styleUrls: ['./static-component-example.css']
})
export class StaticComponentExample {
menuComponent = MenuComponent;
}
`$3
For more detailed examples, see the components included in the demo application.
Building the SDK
You can build the SDK using the following command:
`bash
ng build --prod bloomreach-experience-ng-sdk
`To test out builds locally, you can use the example application that you can build and run from the root:
`bash
npm install
npm run start
`API
$3
Service for overriding the default API URLs, which are used for fetching the Page Model
API. Uses both a live and preview URL for the API URL.
#### Methods
-
setApiUrls(newApiUrls: ApiUrls = {}) - None allows you to override the default URLs.
Typically you will only have to define scheme, hostname, port, and contextPath.
See ApiUrls type below for format of the newApiUrls parameter.####
ApiUrls type-
live:
- scheme: String scheme (default: http)
- hostname: String hostname (default: localhost)
- port: number port number (default: 8080)
- contextPath: String site context-path (default: site)
- channelPath: String path to the used channel, if channel is accessed through a
subpath
- previewPrefix: String preview-prefix used by CMS (default: _cmsinternal)
- apiPath: String path to Page Model API as subpath (default: resourceapi)
- apiComponentRenderingUrlSuffix: String (default: _hn:type=component-rendering&_hn:ref=)
- preview: same as live (see above)$3
The component mapping maps CMS catalog components to Angular components, so that Angular
knows what components to use for rendering the components in the Page Model API response.
#### Methods
-
setComponentMappings(componentMappings: ComponentMappings) - None sets the component
mappings. Expects as input an object with the hst:label of the CMS components as keys
and as value the Angular component used for rendering the component.#### Example
`typescript
import { Component, OnInit } from '@angular/core';
import { ComponentMappingsService } from 'bloomreach-experience-ng-sdk';export class ComponentMappingExampleComponent implements OnInit {
constructor(private componentMappingsService: ComponentMappingsService) {}
ngOnInit() {
const componentMappings = {
'Banner': BannerComponent
}
this.componentMappingsService.setComponentMappings(this.componentMappings);
}
}
`$3
Generates URLs to images for any images that are served directly from BloomReach
Experience.
#### Methods
-
getImageUrl(imageRef) - String returns URL of image using imageRef, the JSON
Pointer that references the image.
- getImageUrlByPath(imagePath: string, variant: string) - String returns URL of image
using its relative-path and the name of the image-variant.$3
Service that handles initialization of the SDK, including:
- Fetching initial Page Model via
PageModelService, and updates to the Page Model on
navigation changes or component updates in the CMS.
- Initializating the Channel Manager integration.
- Restoring the Page Model state using Transfer State API. To use it import ServerTransferStateModule on the server and BrowserTransferStateModule on the client.#### Methods
-
initialize({initializePageModel = true, initializeRouterEvents = true}): Subscription | void - initializes the SDK by fetching the Page Model and initializing the Channel manager integration. Returns router events subscription or void if initializeRouterEvents is false.
- initializePageModel: boolean - flag to fetch the Page Model on initialization;
- initializeRouterEvents: boolean - flag to subscribe for router events.$3
Fetches the Page Model API and manages state.
#### Methods
-
getPageModel() - Object return the Page Model. Please note that this is a
synchronous call, so if this is called during initialization, the Page Model might not
have been set yet. Use getPageModelSubject() in these cases.
- setPageModel(value: any) - update the Page Model and push the value to the Page Model subject (see getPageModelSubject()).
- getPageModelSubject() Subject