Installation

Before we can jump into coding, we need to change our npm registry endpoint and install all dependencies.

1. Additional NPM Registry

Please follow the documentation in ngx-ndbx on how to setup the npm registry configuration.

2. Installation of the library

2.1. Major Versions

The latest stable version can be installed like this:

npm install @allianz/ngx-pfe --save

Beta Versions

Beta versions are published under the npm next dist-tag. The following command displays the latest version per tag:

npm view @allianz/ngx-pfe@* dist-tags

The following command can be used to install the latest beta version:

npm install @allianz/ngx-pfe@next --save

Automatic updates (ng update)

The NGX-PFE provides support for Angular schematics to automatically handle breaking changes during an update. The schematics will run during the update and update the app code accordingly.

Run the following command to update to the latest stable version:

ng update @allianz/ngx-pfe

Changelog

The changelog can be found here

Peer Dependencies

The NGX-PFE library requires some peer dependencies to function correctly.

NDBX is only required, if the ndbx master page is used. Otherwise it is optional.

A full list of dependencies can be seen in the library package.json.

NPM will also automatically mention unavailable peer dependencies during the installation. Please ensure, that all of them are installed.

Peer Dependencies of secondary entries

Unfortunately, there is no way in npm to limit peer dependencies to a secondary entry.

To keep the list of the main entry point peer dependencies as short as possible, the ones from the secondary entries were not added there.

As there is no information from npm about the secondary peer dependencies, the easiest way to figure them out is:

  1. Add the import from the secondary entry
  2. Check the compiler errors, which will mention the missing dependencies
  3. Install the dependency. The version can be taken from the package.json of the ngx-pfe repository

3. How to Integrate NGX-PFE within an App

In this first part, the general module setup is done. In the second part, the page setup is added.

3.1. Prerequisites

First, generate a new Angular app with:

npx @angular/cli new --style=scss --routing pfe-example

This guide assumes that the optional ngx-ndbx integration is used, so keep in mind to also install it.

After that, the pfe itself can be installed:

npm install @allianz/ngx-pfe

3.2. PFE Module Setup

To use the library, the main module (NgxPfeModule) and configuration data model (NgxPfeModuleConfiguration) has to be imported.

Furthermore, the angular routing has to be setup. The pfe takes over one route and adds all the pages there.

It is recommended to create a separate PfeIntegrationModule for the NgxPfeModule setup.

Generate the module with the Angular CLI

npx ng generate @schematics/angular:module --name=PfeIntegration --no-interactive

and replace the content of the pfe-integration-module.module.ts file with this:

import {
  NgxPfeModule,
  NgxPfeModuleConfiguration,
  NGX_PFE_CONFIGURATION,
  NGX_PFE_CONFIG_API_FORMAT,
  NGX_PFE_FLOW_CONFIGURATION,
} from '@allianz/ngx-pfe';
import { NgModule } from '@angular/core';
import { pages } from '../pages-mapping';
import { pfeConfig } from '../pfe-config';

// This factory function is responsible to return the module config for the PFE
export function ngxPFEConfigFactory() {
  // The factory function can also define dependencies, for example
  // embeddedDataService: EmbeddedDataService<undefined, AEMConfiguration>
  // This service could then be used to get configurations:
  // const applicationId = embeddedDataService.CustomConfiguration.applicationId || environment.applicationId;

  const ngxPfeModuleConfiguration: NgxPfeModuleConfiguration = {
    /**
     * Maps the configuration attributes to a PageDefinition. This defines the available page types that can be used in the flow.
     */
    pageMapping: pages,
    /**
     * The tenant will be used to load the default page flow configuration.
     * It can be overwritten by the tenant URL parameter.
     */
    tenant: 'tenant',
    /**
     * The applicationId will be used to load the default page flow configuration.
     * It can be overwritten by the applicationId URL parameter.
     */
    applicationId: 'app',
    // The configuration can also be loaded over HTTP:
    // configApiEndpoint: 'http://localhost:4200/assets/config',
    // configApiFormat: NGX_PFE_CONFIG_API_FORMAT.STATIC,
    production: true,
    /**
     * The base URL of service activator endpoint.
     * It will be composed with the service activator `path` to form a complete URL.
     * This complete URL is used when service activators make any HTTP calls.
     */
    serviceActivatorEndpoint: 'http://localhost:8080',
  };
  return ngxPfeModuleConfiguration;
}

@NgModule({
  imports: [
    NgxPfeModule.forRoot({
      provide: NGX_PFE_CONFIGURATION,
      /**
       * The factory can return a static value or an Angular signal
       */
      useFactory: ngxPFEConfigFactory,
    }),
  ],
  providers: [
    {
      provide: NGX_PFE_FLOW_CONFIGURATION,
      /**
       * The factory can return a static value, a Promise or an Angular signal
       */
      useValue: pfeConfig,
    },
  ],
})
export class PfeIntegrationModule {}

Configuration Parameters

Module Configuration

The NgxPfeModuleConfiguration contains the configuration of the NGX-PFE library. In this example, they are provided by the ngxPFEConfigFactory.

The (NgxPfeModuleConfiguration) describes all the parameters.

Flow Configuration

In this example the flow configuration is provided directly via the NGX_PFE_FLOW_CONFIGURATION token. The Pages & Flow Configuration documentation contains further instructions on how to provide it. An template for the example application is also provided there.

3.3. Root Routing Integration

The simplest routing integration is for the PFE to take over the root routing of the app.

The example AppRoutingModule below shows this integration of the PFE directly in the root.

⚠️ VERY IMPORTANT: The routing setup has to be done after the NgxPfeModule import.

It is recommended to generate a separate AppRoutingModule.

npx ng generate @schematics/angular:module --name=AppRouting --no-interactive

Afterwards, open the app-routing-module.module.ts and replace the content with this:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('@allianz/ngx-pfe').then((m) => m.NgxPfeRoutingModule),
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

Optional LocationStrategy

If the application is integrated into a CMS, like oneMarketing, it is recommended to use the HashOnlyLocationStrategy provided by the PFE. This custom strategy will keep the url search parameter part intact.

The LocationStrategy can be added to the providers of the app:

providers: [
  {provide: LocationStrategy, useClass: HashOnlyLocationStrategy}
]

3.4. AppModule Setup

Now the app.module.ts can be updated with the new modules:

import { PfeNdbxMasterPageModule } from '@allianz/ngx-pfe/ndbx';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing/app-routing.module';
import { AppComponent } from './app.component';
import { PfeIntegrationModule } from './pfe-integration/pfe-integration.module';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    PfeIntegrationModule,
    AppRoutingModule,
    // By default the PfeNdbxMasterPageModule can be used:
    PfeNdbxMasterPageModule,
  ],
  providers: [provideHttpClient(withInterceptorsFromDi())],
  bootstrap: [AppComponent],
})
export class AppModule {}

4. PFE Master Page

After adding the pfe to the routing and registering page types with it, the rendering of the pages needs to be setup.

The main entry point/router outlet for the page flow display is the PFE Master Page.

There are two versions available:

  • An empty master page, where all the sections have to be supplied as templates:pfe-master-page. This page is suited for use cases where a very custom design/UI is used.
  • An ndbx based master page, that provides some default components, for example for the navigation buttons. This component also provides the possibility to override certain parts.

In general it is recommended to use the ndbx based one, if the app is ndbx based.

It can be used in the following way in the app.component.ts:

<pfe-ndbx-master-page></pfe-ndbx-master-page>

Alternatively, it is also possible to create a custom setup/component for the pfe router outlet.

5. Localization

Translation of texts within the pfe is required for these use cases:

  • When the default navigation buttons are used (PfeNavButtonsContainerComponent)
  • When the default display of error messages for server responses is used and these should be translated

If custom templates are used for this or no translation is needed, it is not necessary to import any translation adapter.

The PFE supports two different translation tools/libraries out of the box:

The usage of a translation tool/library is activated by importing the respective module:

  • PFENgxTranslateAdapterModule
  • PFEAngularTranslateAdapterModule

The import has to be located below the NgxPfeModule import. (The order of imports matters in Angular) For example, like this:

NgxPfeModule.forRoot({
  provide: NGX_PFE_CONFIGURATION,
  useFactory: ngxPFEConfigFactory
}),
// Activate this import, to use ngx-translate
// PFENgxTranslateAdapterModule,
// Activate this import, to use the native Angular translate:
PFEAngularTranslateAdapterModule,

A prerequisite for the usage of those modules is the setup/configuration of the translate tool/library.

5.1. Support of custom translation solutions

It is possible to add support for further translation tools/libraries by implementing a custom version of the PFETranslateService.

It can be supplied as a provider:

{
  provide: PFETranslateService,
  useClass: MyCustomTranslateAdapterService,
}

5.2. NGX-Translate i18n-from-state

If ngx-translate is used for the translations, the pfeI18nFromState pipe and the pfeI18nFromState directive can be used.

They take a value from the state and use it as a translation key with ngx-translate.

As they depend on ngx-translate, they are located in a secondary entry: @allianz/ngx-pfe/util/i18n-from-state.

This functionality is not available with the Angular native translation, as dynamic translation keys are not supported by it.

6. Other Integration Scenarios

6.1. Integration into an App with a Parent Routing

In most cases, the ngx-pfe is integrated into the main routing entry point of an app. Alternatively, it is also possible to integrate it as a child into the existing routing of an app.

The integration itself is pretty much the same as in the routing root of an app. But there are a few caveats to be taken care of.

Routing Setup

In this example, the pfe is integrated into the parent routing like this:

const routes: Routes = [
  { path: 'some-route', component: SomeComponent },
  {
    path: 'pfe-journey',
    loadChildren: () => import('./pfe-journey/src/app/entry.module').then((m) => m.EntryModule),
  },
  {
    // More routes
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

The EntryModule for the journey imports the pfe, setups the routing and can also contain a wrapper around the pfe content.

It is very important, that the routing of the EntryModule is setup in its own module and imported as the first module within the EntryModule.

The routing module looks like this:

const routes: Routes = [
  {
    path: '',
    component: EntryComponent,
    children: [
      {
        path: '',
        loadChildren: () => import('@allianz/ngx-pfe').then((m) => m.NgxPfeRoutingModule),
      },
    ],
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class EntryRoutingModule {}

This module is then imported in the EntryModule:

@NgModule({
  declarations: [EntryComponent],
  imports: [
    EntryRoutingModule,
    NgxPfeModule.forRoot({
      provide: NGX_PFE_CONFIGURATION,
      useFactory: ngxPFEConfigFactory,
    }),
  ],
  providers: [],
  exports: [RouterModule],
})
export class EntryModule {}

The EntryComponent can then either use the master page from the pfe or define a custom wrapper/navigation and simply provide a router-outlet.

6.2. UI Navigation Integration of the Parent App

The integration as a module in the parent routing has a catch that needs to be handled by the parent navigation.

If a user navigates to the pfe journey via a navigation menu that uses the Angular routerLink, it is possible for the user to trigger that navigation again, while the pfe is already active. This causes the Angular router to jump back to the initial route of the link and will break the journey.

Unfortunately, there is no way for the pfe to intercept and to prevent this from happening (Route Guards actually do not fire). This means, the parent app needs to take care to deactivate the routerLink when the journey is already active.

Luckily, this can be done with the routerLinkActive functionality and a bit of css to disable the pointer-events

For example, with the following navigation link:

<a class="nav-link" routerLink="/pfe/journey" routerLinkActive="active"><span class="nav-text">Live Demo</span></a>

And this corresponding css to deactivate the link while it is active:

.nav-link.active {
  pointer-events: none;
}

results matching ""

    No results matching ""