This is a collection of advanced use cases and example implementations. If you are new to Luigi, take a look at our Getting Started section first.
This example shows you how to keep an existing routing strategy and use an existing micro frontend as drop-in without the need to refactor everything to LuigiClient.linkManager()
. To update the Luigi Core URL when routing internally with the micro frontend router, without updating the URL on the Luigi Client side, use the linkManager()
withoutSync and fromVirtualTreeRoot methods.
If you are running Luigi Core v0.7.7+, you can use fromClosestContext instead of fromVirtualTreeRoot
, which requires a navigationContext at the virtualTree
node configuration.
NOTE: This is a very simple example. For cases like modals or split views, you still require the use of Luigi Client.
- Configure the Luigi navigation node:
NOTE: To keep the example simple, we use virtualTree to allow any nested navigation, but this is not mandatory. You can always specify the node tree yourself and still use automatic navigation with router events.
{
pathSegment: 'Orders',
label: 'orders',
viewUrl: 'https://orders.microfrontend/',
virtualTree: true
}
- Use an Angular Router for navigation.
Angular provides Router events. We are reacting on NavigationEnd
to update the URL after a successful route change.
We assume that the whole Angular app is one micro frontend and has its routes declared on the root level:
{ path: 'preload', component: PreloadComponent },
{ path: '', component: OrderListComponent },
{ path: ':id', component: OrderComponent },
{ path: ':id/details', component: OrderDetailsComponent },
Use this code to implement luigi-auto-navigation.service.ts
, which is globally imported in our app.module.ts
:
import { Router, NavigationEnd } from '@angular/router';
import { Injectable, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { linkManager } from '@luigi-project/client';
@Injectable({ providedIn: 'root' })
export class LuigiAutoNavigationService implements OnDestroy {
private subscriptions: Subscription = new Subscription();
constructor(private router: Router) {
this.subscriptions.add(
router.events
.pipe(filter(ev => ev instanceof NavigationEnd))
.subscribe((ev: NavigationEnd) => {
linkManager()
.fromVirtualTreeRoot()
.withoutSync()
.navigate(ev.url);
})
);
}
ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}
}
app.module.ts
:
@NgModule({
providers: [LuigiAutoNavigationService],
Other than the added service, which you can also implement as a RouteGuard
or similar, the micro frontend is unchanged and uses [routerLink='']
or other functionality to navigate.
This example shows you how to use Luigi with a Google account.
- Register a project and generate an OAuth2 Web Client based on Google Developers Identity - OAuth2UserAgent.
- To get your app running locally, set the Authorized JavaScript Origins URIs to
http://localhost:4200
and Authorized redirect URIs tohttp://localhost:4200/luigi-core/auth/oauth2/callback.html?storageType=localStorage
. - Copy the Client ID which ends with
apps.googleusercontent.com
. - Update the LuigiConfig auth section. In this example, we have also provided a configuration for logout and getting user information:
{
auth: {
use: 'oAuth2ImplicitGrant',
oAuth2ImplicitGrant: {
authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
oAuthData: {
response_type: 'id_token token',
client_id: 'YOUR_CLIENT_ID...apps.googleusercontent.com',
scope: 'openid https://www.googleapis.com/auth/userinfo.email profile',
}
},
logoutFn: async (settings, authData, logoutCallback) => {
console.log('revoking token');
await fetch(`https://accounts.google.com/o/oauth2/revoke?token=${authData.accessToken}`);
logoutCallback('/logout.html');
}
}
}
Google's id_token
contains basic identity data like name and user ID, which allows for this data to be shown in the profile.
5. If you would also like to show the user picture, add the following code to enrich the user profile information:
userInfoFn: async (settings, authData) => {
const response = await fetch('https://www.googleapis.com/oauth2/v1/userinfo', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + authData.accessToken
}
});
const json = await response.json();
return json;
},
There are two possibilities to add feature toggles to the active feature toggles list. On the one hand you can use the core api and on the other hand it is possible to add a feature toggle through url parameters.
Luigi allows you to implement and configure feature toggles. They can be used to organize and compartmentalize your code.
- To set feature toggles, you have two possibilities:
- Set feature toggles to the active feature toggle list through Luigi Core API:
Luigi.featureToggles().setFeatureToggle('ft1');
- Set feature toggles to the active feature toggle list via URL parameters:
http://localhost:4200/projects/pr1?ft=ft1,ft2
- To unset feature toggles, you have to use the Core API:
Luigi.featureToggles().unsetFeatureToggle('ft1');
- To restrict node visiblity with feature toggles:
You can define a list of feature toggles for a particular top or left navigation node. Then, you can use the visibleForFeatureToggles parameter in order to display the node for certain feature toggles.
For example, this node will be visible if
ft1
is added to the active feature toggle list:It is also possible to negate the visibility of a node by adding an exclamation mark at the beginning of the feature toggle name. In this example, the node is always visible except if{ category: { label: 'Feature Toggle: Settings 2', icon: 'action-settings' }, pathSegment: 'settings_ft', label: 'Project Settings 2', viewUrl: '/sampleapp.html#/projects/' + projectId + '/settings', icon: 'settings', visibleForFeatureToggles: ['ft1'] }
ft1
is set as an active feature toggle:{ category: { label: 'Feature Toggle: Settings 2', icon: 'action-settings' }, pathSegment: 'settings_ft', label: 'Project Settings 2', viewUrl: '/sampleapp.html#/projects/' + projectId + '/settings', icon: 'settings', visibleForFeatureToggles: ['!ft1'] }
- To use feature toggles in a micro frontend:
It is possible to restrict content in a micro frontend using feature toggles. The active feature toggle list is available in the Luigi Client API.
if (LuigiClient.getActiveFeatureToggles().includes('ft1')) { //display content }
Luigi Client allows you to navigate through micro frontends by using an intent-based navigation. This type of navigation decouples navigation triggers from the actual navigation targets. Rather than directly encoding the name of the target app into the URL fragment, app developers provide a navigation intent such as display
or edit
as shown in the examples below.
-
To enable intent-based navigation, you need to first identify the necessary target mappings. This can be done by defining
intentMapping
in the Luigi configuration undernavigation
as in the example below:intentMapping = [ { semanticObject: 'Sales', action: 'display', pathSegment: '/projects/sap/munich/database/sales/display' }, { semanticObject: 'Sales', action: 'edit', pathSegment: '/projects/sap/munich/database/sales/edit' } ];
- The intent link is built using the
semanticObject
,action
and optional parameters in the following format:#?intent=semanticObject-action?params
. An example of an intent link would be as follows:
#?intent=Sales-edit?id=100
- Navigation to a micro frontend through this intent is then made possible by using the linkManager navigate method from Luigi Client API:
LuigiClient.linkManager().navigate('#?intent=Sales-edit?id=100');
- This method would then be navigating to the translated real path segment:
https://example.com/projects/sap/munich/database/sales/edit?~id=100;
- Alternatively, the intent link can also be accessed through the browser URL and accessed from outside:
https://example.com/#?intent=Sales-edit?id=100;
- The intent link is built using the