TIP: To see the navigation parameters in use, see the navigation configuration example or configure a test application in the Luigi Fiddle.
Use the parameters and functions in this reference to configure your Luigi navigation structure.
You can configure the way Luigi tackles routing in your application in the routing:
section of the configuration file. For example, you can choose the routing strategy to apply in your application as either hash or path location routing.
false
LuigiClient.linkManager().openAsModal()
function, which provides a simple way to bookmark a modal view URL. It is appended as query param to the base URL. An example would be example.com/your/path?modal=/another/path
. This setting requires routing.showModalPathInUrl
to be set to true
to be effective.modal
, but you may also define a custom one.LuigiClient.linkManager().withParam()
function, which provides a simple way to attach query parameters to a view URL for activities such as sorting and filtering. Only this prefix can pass query parameters to micro frontends. A different prefix has to be used to pass parameters to the Luigi app itself to avoid potential conflicts between the two.~
, but you may also define a custom one.404
error occurs. Luigi handles it by default. Leave its body empty if you have an external 404
handling. You can return an Object with redirectTo and keepURL as parameters. You can use the redirectTo parameter if you want Luigi to redirect to a specific navigation path after execution. Setting the keepURL parameter to true
will keep the erroneous URL onto the browser's address bar.
If you don't want Luigi to handle the page not found error, because you've implemented your own function for this purpose, you can return an Object with ignoreLuigiErrorHandling set to true
.
false
, which means query parameters are not persisted in the URL after navigation request.false
routing.modalPathParam
setting.false
, which means no modal paths are shown in the URL.[/access_token=/, '/id_token=/]
.example.com/#/yourpath
) or path-based (example.com/yourpath
) routing.false
, which means path routing is used.The navigation parameters allow you to configure global navigation settings directly under the navigation:
section in the configuration file.
true
, proper href attributes are added to all navigation links. It is set to false
by default.title
for all expand and collapse buttons on categories. It is possible to override the default to define a title on an individual category by itself.title
attribute with the defined value to the expand button.title
attribute with the defined value to the collapse button.config.navigation.defaults = {
category: {
titleExpandButton: 'Expand category',
titleCollapseButton: 'Collapse category',
}
}
false
by default, and you can overwrite it using the isolateView value on a single node level.config.navigation.defaults = {
isolateView: true
}
NOTE: The pageErrorHandler only works if the loading indicator is not disabled.
config.navigation.defaults = {
pageErrorHandler: {
timeout: 500,
viewUrl: '/some/view/url',
redirectPath: '/projects/pr2',
errorFn: ()=> {}
}
}
true
, only one category is collapsed. The navigation is similar to an accordion; when the user clicks another category the previously collapsed category is closed and the new one is opened.false
config.navigation.defaults = {
sideNavAccordionMode: true
}
false
, all tooltips will be hidden. If it is Some string text
, all tooltips will have the value Some string text
.undefined
by default. config.navigation.defaults = {
tooltipText: 'Default tooltip text'
}
display
, approve
or edit
. The operation is intended to be performed on a semanticObject such as a sales order or a certain product. It can only contain alphanumerical characters but also the underscore character.true
, opens the specified URL in a new tab. Otherwise, it opens it in the current tab.false
, Luigi removes the node and its children from the navigation structure. See angular navigation.js for an example.nodes:
attribute. First-level nodes are also referred to as "root nodes". Second-level nodes can be defined inside a children array below the root node.
In addition to an array, nodes:
can also be defined as a single node object which then serves as the root node.
In this case, the root node should not have a pathSegment defined, because it is accessible through the empty path. If you define a pathSegment
anyway, you should see a warning about this in the console.
// Nodes array
navigation: {
nodes:[{
pathSegment: 'home'
label: 'Root node',
viewUrl: 'home.html',
children: [
{
pathSegment: 'sample1',
label: 'Sample',
viewUrl: 'sample1.html'
}
]
}]
}
// Root node as an object
navigation: {
nodes:{
label: 'Root node',
viewUrl: 'home.html',
children: [
{
pathSegment: 'sample1',
label: 'Sample',
viewUrl: 'sample1.html'
}
]
}
}
...
settings: {
navigation: {
validWebcomponentUrls:[
'https\:\/\/YOURPROJECT\.gitlab\.io\/.?'
]
}
true
, it loads the respective view group with the respective preloadUrl in the background as soon as the app first starts.Node parameters are all the parameters that can be added to an individual navigation node in the nodes:
section of the Luigi configuration file.
alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.true
, the node is always accessible. When set to exclusive
, the node is only visible in logged-out state. Requires auth.disableAutoLogin to be set to true
. anonymousAccess needs to be defined both on parent and child nodes.Luigi.navigation().updateTopNavigation()
in Luigi Core or trigger it in Luigi Client by using the custom message feature.
label
value.sap-icon--
prefix. Its source may be OpenUI5 or a custom link (relative or absolute) to an image. It is recommended to use a square image. The icon is displayed next to the node label in the side navigation or instead of the label in the top navigation. In case you accidentally define different icons in a category group, only the first one is used.alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.true
, category items are hidden at first. To expand them, click the main category node.testId
for E2E tests. If nothing is specified, it is the node's label written as one word in lower case, for examplelabel
.id
will be grouped.title
attribute with the defined value to the expand button.title
attribute with the defined value to the collapse button.navigation: {
nodes: [{
pathSegment: 'home',
label: 'h',
hideFromNav: true,
children: [{
pathSegment: 'overview',
label: 'Overview',
icon: 'home',
viewUrl: '/examples/microfrontends/multipurpose.html',
context: {
title: 'Welcome to Luigi Fiddle!',
content: 'Click on "Modify Config" at the bottom right and play around with your Luigi configuration'
}
},
...
{
pathSegment: 'ui5sc',
label: 'Shopping Cart',
category: 'UI5 Demo Pages',
hideSideNav: true,
loadingIndicator: {
enabled: false
},
viewUrl: 'https://sdk.openui5.org/test-resources/sap/m/demokit/cart/webapp/index.html'
}]
...
}]
}
// Example of Children as a Promise
navigation: {
nodes: [{
...,
children: () => {
return new Promise((resolve, reject) => {
fetch('/node/endpoint').then((...)=>{
...
resolve(nodes);
});
})
},
...
}]
}
true
clientPermissions: {
changeCurrentLocale: true
}
clientPermissions:{
urlParameters:{
q:{
write: true,
read: true
}
}
}
<header><slot name="header">header</slot></header>
.
Web components can communicate over an event bus.
grid
, or implement an extended layout by defining an object using the extends
property. In that case you have the possibility to implement the following functions to manipulate the standard renderer.grid
config
object as parameter.config
object and the layout config object for the item.grid-template-columns
, e.g 1fr 2fr
.grid-template-rows
, e.g. 150px 150px
.grid-gap
, e.g. auto
.grid-template-columns
, e.g 1fr 2fr
.grid-template-rows
, e.g. 150px 150px
.grid-gap
, e.g. auto
.rootMargin
option for the intersection observer. In short, this allows configuring that child web components are instantiated before or after their containers enter the viewport.type: string
default: "500px"
description: When lazy loading is active, the containers for all children will be created with a fixed, temporary height. That is because otherwise, when adding the empty containers for all children, all containers would have a height of 0. All containers would be visible so that all web components would be added right away. In other words, this would break lazy loading.
This attribute must be a valid CSS height string. Its value will be used for the default temporary height for all children. Individual children can override this default with their own value, see below.
After the web component of a child is rendered and attached to its container, the temporary height will be removed from the container.
true
will turn off that behavior. In that case, the custom renderer methods and the code of the child web components must ensure that not all child containers are visible right away. Note that the intersection observer will still be in effect: child web components will only be instantiated and added to their containers when the containers are visible in the defined part of the viewport.id
of the web component..js
file. If you are using localization and translating your page into different languages, you can also add a {i18n.currentLocale} parameter to the viewUrl part of your configuration.grid-row
value in the CSS grid standard. Use it to define the position of the child item in the grid.grid-column
value in the CSS grid standard. Use it to define the position of the child item in the grid.row
and column
to define the slot into which to render this child. In that case this web component node will be plugged in that slot of the parent web component.temporaryContainerHeight
that is set for the overall compound.id
of the web component, which you want to listen. Alternatively you can set an asterisk, e.g. *
update
.{
pathSegment: 'webcomponent',
label: 'Webcomponent',
icon: 'along-stacked-chart',
loadingIndicator: {
enabled: false
},
context: {
title: 'Hello WebComponent!'
},
viewUrl: '/helloWorldWC.js',
webcomponent: true,
openNodeInModal: true
},
Below is Luigi's web component example configuration which shows 3 web components in a grid layout. It also includes the configuration for the event bus. The input
web component sends the typed input. The header
web component listens to a sendInput
event from a web component with the id input1
. Received data will be converted. An update
event will be triggered, changing the header
web component where an update
event listener is registered.
{
pathSegment: 'wc_grid',
label: 'Grid',
category: {
label: 'Compound',
icon: 'attachment-html',
collapsible: true
},
compound: {
renderer:
{
use: 'grid',
config: {
columns: '1fr 1fr 1fr',
/*rows: '150px',*/
/*gap: '30px',*/
layouts: [{
minWidth: 0,
maxWidth: 600,
columns: '1fr',
gap: 0
}, {
minWidth: 600,
maxWidth: 1024,
columns: '1fr 1fr',
gap: '30px'
}]
}
},
children: [{
viewUrl: 'URL_TO_HEADER_WEBCOMPONENT/panelHeader.js',
context: {
title: 'My Awesome Grid',
description: 'Really awesome'
},
layoutConfig: {
row: "1",
column: "1 / -1"
},
eventListeners: [{
source: 'input1',
name: 'sendInput',
action: 'update',
dataConverter: (data) => {
return 'new text: ' + data;
}
}]
}, {
id: 'input1',
viewUrl: 'URL_TO_SOME_WEBCOMPONENT/input.js',
context: {
title: 'Some input test',
instant: true
}
},
{
viewUrl: 'URL_TO_FOOTER_WEBCOMPONENT/panelFooter.js',
context: {
footer: 'This is the end of awesomeness'
},
layoutConfig: {
column: "1 / -1"
}
}]
}
}
NOTE: To define a root-level defaultChildNode which is different than the first header navigation node, set an object with defaultChildNode and children set to
navigation.nodes
instead of an array of nodes.
settings: {
navigation: {
nodes: {
defaultChildNode: 'overview',
children: [
{
pathSegment: 'docs',
label: 'Documentation',
viewUrl: '...'
},
{
pathSegment: 'overview',
label: 'Overview',
viewUrl: '...'
}
]
}
}
NOTE: The runTimeErrorHandler only works if the micro frontend uses Luigi Client and disable-luigi-runtime-error-handling is not disabled.
error
as parameter. The properties of this object are the properties of the error event. The inherited properties from event are not part of the object. Current node is the second parameter.runTimeErrorHandler: {
errorFn: (error, currentNode)=>{}
}
false
.
true
, the global search disappears when you click the affected node.false
true
, the left navigation disappears when you click the affected node.false
sap-icon--
prefix. Its source may be OpenUI5 or a custom link (relative or absolute) to an image. It is recommended to use a square image. The icon is displayed next to the node label in the side navigation or instead of the label in the top navigation. To show the label next to the icon in the top navigation, add the showLabel
attribute.true
, it forces navigation to the empty viewUrl node.false
NOTE: For iframe integration of views, which don't have Luigi Client, loading indicator should be disabled.
true
loadingIndicator: {
enabled: false
}
false
, it disables the automatic hiding of the loading indicator once the micro frontend is loaded. It is only considered if the loading indicator is enabled. It does not apply if the loading indicator is activated manually with the LuigiClient.uxManager().showLoadingIndicator()
function. If the loading indicator is enabled and automatic hiding is disabled, use LuigiClient.uxManager().hideLoadingIndicator()
to hide it manually in your micro frontend during the startup.true
loadingIndicator: {
hideAutomatically: false
}
LuigiClient.linkManager().fromContext('contextname')
.false
, the navigation is not triggered, otherwise, navigation renders as usual.true
to use the default modal title and size, or you can specify them using these attributes:l
, which means 80% of the main window size. You can also use m
(60%) and s
(40%) to set the modal size or%
, px
, rem
, em
, vh
and vw
.NOTE: The pageErrorHandler only works if the loading indicator is not disabled.
timeout: 500
).settings
results in example.com/settings
.false
for that node. See the advanced navigation document for more information.navigation: {
nodes: [{
pathSegment: 'home',
showBreadcrumbs: false,
...
true
, only one category is collapsed. The navigation is similar to an accordion; when the user clicks another category the previously collapsed category is closed and the new one is opened. Note that this will be applied to its direct children.false
negative
, positive
, critical
, informative
, or neutral
. The default is neutral
.right
or left
. The default is left
.{
pathSegment: 'settings',
label: 'Settings',
viewUrl: '/sampleapp.html#/settings',
statusBadge: {
label: 'Settings',
type: 'positive'
}
}
type: boolean or Object
description: renders the children of the node as a horizontal navigation bar. Sub-children are not supported. When you categorize nodes, you will get a drop-down menu in the horizontal navigation. Set to true
to show the horizontal navigation, or use the extra attributes for more customization. (since: v0.7.0)
attributes:
true
to hide the horizontal navigation bar and false
otherwise. ( since: v2.0.0 )example:
// Without hiding tab nav automatically
pathSegment: 'example',
label: 'Example',
tabNav: true,
children: [
...
// With hiding tab nav automatically if node has only one child
pathSegment: 'example',
label: 'Example',
tabNav: { hideTabNavAutomatically: true },
children: [
...
// showing horizontal navigation header micro frontend
pathSegment: 'header',
label: 'Header Micro frontend',
viewUrl: '/tabHeader.js'
webcomponent: true,
tabNav: { showAsTabHeader : true },
children: [
...
pathsegment_label
or label
.false
.undefined
by default, and it can be overwritten by using the tooltipText value on a single node level.tooltipText: 'Useful links'
false
. Instead, the children will be rendered in the left navigation (default) or in the horizontal navigation (tabNav) if this is configured on the node. This feature only works if the nodes property is an object instead of an array. In that case, the root node will not be reflected in the URL.true
, meaning that children of the root node show in the top navigation.navigation: {
nodes: {
pathSegment: "",
hideFromNav: true,
tabNav: true,
topNav: false,
hideSideNav: true,
viewUrl: 'https://fiddle.luigi-project.io/examples/microfrontends/multipurpose.html',
context: {
title: 'root'
},
children: [
{
pathSegment: "SampleApp1",
label: "SampleApp1",
viewUrl: 'https://fiddle.luigi-project.io/examples/microfrontends/multipurpose.html',
context: {
title: 'Sample app 1',
content: 'Sample app 1'
}
},
{
pathSegment: "SampleApp2",
label: "SampleApp2",
viewUrl: 'https://fiddle.luigi-project.io/examples/microfrontends/multipurpose.html',
context: {
title: 'Sample app 2',
content: 'Sample app 2'
}
}]
}
}
userSettingGroups
object. For more information, read the section on user settings.{
category: { label: 'Settings', icon: 'action-settings' },
pathSegment: 'user_settings',
label: 'User Settings',
viewUrl: '/sampleapp.html#/projects/' + projectId + '/settings',
icon: 'settings',
userSettingsGroup: 'userAccount',
testId: 'myTestId',
}
true
and provide a preload URL for your view group ID in viewGroupsSettings.
For further explanations, see this section.
settings: {
navigation: {
preloadViewGroups: true,
viewGroupSettings:{
view_group_components: {
preloadUrl: '.....'
}
},
nodes: {
defaultChildNode: 'overview',
children: [
{
pathSegment: 'docs',
label: 'Documentation',
viewGroup: 'view_group_components',
viewUrl: '...'
},
{
pathSegment: 'overview',
label: 'Overview',
viewGroup: 'view_group_components',
viewUrl: '...'
}
]
}
}
core.tld/settings/some/nested/view
will result in opening /sampleapp.html#/settings/some/nested/view
.
{
pathSegment: 'settings',
label: 'Settings',
viewUrl: '/sampleapp.html#/settings',
navigationContext: 'settings',
virtualTree: true
}
!
in front of the toggle name. Then, the node is always visible except for the feature toggle defined with an exclamation mark.{
pathSegment: 'settings',
label: 'Settings',
viewUrl: '/sampleapp.html#/settings',
navigationContext: 'settings',
visibleForFeatureToggles:['ft1', '!ft2']
}
true
or defining an object with the attributes described below. In the latter case, the viewUrl
attribute of the node must point to the web component .js
file.module
.true
, the web component bundle will be added via script tag.NOTE: If you have to use the mechanism of
selfRegistered
, we recommend using the following code in your web component:
window.Luigi._registerWebcomponent(new URL(document.currentScript?.getAttribute('src'), location), <YOUR_WEBCOMPONENT_CLASS>);
The advantage of this line of code is: you don't have to specify a tag name, thus avoiding the duplication of self-defined tag names.
The context switcher is a drop-down list available in the top navigation bar. It allows you to switch between a curated list of navigation elements such as Environments. To do so, add the contextSwitcher parameter to the navigation object using the following optional parameters:
testId
for E2E tests. If nothing is specified, it is the node's label written as one word and lower case (e.g. label
).top
or bottom
. The default value is top
. This parameter
is optional.
true
, link is opened afterwards.false
, the drop-down is not shown on click if there is only one option and no actions.true
<button>
. The function takes an option object as a parameter. It is recommended to use this function carefully because it is possible to inject JavaScript code.<li>
element. The function takes an option object and a boolean isSelected as a parameter. It is recommended to use this function carefully because it is possible to inject JavaScript code.true
, loads options when you click the context switcher. It doesn't involve any caching. When set to false
, loads options once the page loads.true
true
, the sub-path is preserved on context switch.true
, the labels retrieved through fallbackLabelResolver are cached within Luigi. This is useful, if fallbackLabelResolver is an async function which does a remote server call to fetch its value.The profile section is a configurable drop-down list available in the top navigation bar. Within the configuration, you can override the logout item content (if authorization is configured) and/or add links to Luigi navigation nodes. To do so, add the profile parameter to the navigation object using the following optional parameters:
testId
for E2E tests. If nothing is specified, it is the node's label written as one word and lower case (e.g. label
).alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.false
.
Sign Out
.testId
for E2E tests. If nothing is specified, it is the node's label written as one word and lower case (e.g. label
).alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.userInfo
function internally. It can be asynchronous and should return an object with name, email and picture parameters.NOTE: Neither authorization nor profile parameter is configured if the profile section in the top navigation bar is not visible.
The product switcher is a pop-up window available in the top navigation bar. It allows you to switch between the navigation elements displayed in the pop-up. To do so, add the productSwitcher parameter to the navigation object using the following optional parameters:
alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.'auto'
. If nothing is specified, it is 4 columns by default. Parameter columns: 'auto'
sets the number of columns to 3, in case the entities in productSwitcher are equal to or less than 6. If there are more than 6, the number of columns will be automatically adjusted to 4.sap-icon--
prefix. Its source may be OpenUI5 or a custom link (relative or absolute) to an image. The icon is displayed without label in the top navigation.testId
for E2E tests. If nothing is specified, it is the node's label written as one word and lower case (e.g. label
).alt
attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.false
.
testId
for E2E tests. If nothing is specified, it is the node's label written as one word and lower case (e.g. label
).The app switcher is a dropdown list available in the top navigation bar. It allows you to switch between application elements displayed in the dropdown. To use it, you need to:
settings:
section of your Luigi configuration.ul
element as slot. You can append your custom li
entries to this ul
element.closeDropDown
as property. This function closes the custom app switcher dropdown. appSwitcher: {
items:[...],
itemRenderer: (item, slot, appSwitcherApiObj) => {
let a = document.createElement('a');
a.setAttribute('class', 'fd-menu__link');
a.addEventListener('click', e => {
Luigi.navigation().navigate(item.link);
appSwitcherApiObj.closeDropDown();
e.stopPropagation();
Luigi.configChanged('navigation')
});
let span = document.createElement('span');
span.setAttribute('class', 'fd-menu__addon-before');
let i = document.createElement('i');
if (item.title === 'Application One') {
i.setAttribute('class', 'sap-icon--phone');
} else {
i.setAttribute('class', 'sap-icon--settings');
}
span.appendChild(i);
let spanText = document.createElement('span');
spanText.setAttribute('class', 'fd-menu__title');
spanText.innerText = item.title;
a.appendChild(span);
a.appendChild(spanText);
slot.appendChild(a);
}
}
The global search is an input field available in the top navigation bar. The search is available if the Luigi configuration file contains on its root level a section called globalSearch
. Within this section you can implement and configure a search provider object.
true
, a searchProvider must be defined in order to show the search field, which can contain your custom logic. It is recommended to initialize your custom logic in the lifeCycle.luigiAfterInit hook.searchFieldCentered
is active. Default value is cancel
and this property is optional.div
element as slot. You can append a custom implementation of the search result to this div
element.fireItemSelected
as property. This function gets a search result item as parameter and fires the search provider event onSearchResultItemSelected
.li
element as slot. You can append a custom implementation of a searchResultItem
to this li
element.fireItemSelected
as property. This function gets a searchResultItem
as parameter and fires the search provider event onSearchResultItemSelected
.searchResultItem
.key
is the language and value
is the text used as placeholder in the search input field. This function doesn't have any input parameter.