Components serve as the core building blocks of OpenUI5 applications. This guide explains the various ways to instantiate components, when to use each approach, and how to migrate from older mechanisms to modern alternatives.
On this page:
OpenUI5 offers several mechanisms for component instantiation, each suited for different scenarios:
ComponentSupport
Module - A declarative approach for initial application components.Component.create()
Factory Function - A modern factory function. This is the recommended approach for programmatic component creation with full application control and responsibility. It requires a ComponentContainer
to render.Component#createComponent()
Factory Function - The recommended approach to create a reuse component defined in an application component’s manifest.json
. It also requires a ComponentContainer
to render.ComponentContainer
- A container element for rendering components. It can load and instantiate a component and accepts any other programmatically created component, such as those created via Component.create()
or Component#createComponent
.OpenUI5 provides two modern component factories:
Component.create()
Component#createComponent()
This section outlines the usage of the Component.create()
API, as it is the most flexible and versatile way to create a component instance. Keep in mind that the full responsibility for component orchestration and rendering lies with the application.
Component.create()
The static Component.create()
factory allows you to pass the name of a component along with additional options like the URL for a manifest.json
. The return value of this factory is a Promise that resolves with the final component instance once it is fully constructed.
Note:
For more information on the manifest, see Manifest First Function.
// Basic factory call
const oBasicComponent = await Component.create({
name: "sap.my.component",
});
You can also pass a dedicated URL for the manifest.json
to the factory function. In this case, the URL must point directly to the manifest.json
and must be resolved by the caller:
// Creating a Component with a manifest URL
const oComponentWithManifestURL = await Component.create({
name: "sap.my.component",
manifest: "any/location/sap/my/component/manifest.json"
});
Component#createComponent()
The Component#createComponent()
factory is explained below in Nesting Components.
The table below shows the recommended approach for each scenario. We recommend initializing the first application component via the ComponentSupport
in the initial HTML page. If needed, you can also create a component programmatically using the Component.create()
factory method in combination with a ComponentContainer
. All recommended approaches support optimized manifest-first loading.
Scenario | Recommended Approach | Reason |
---|---|---|
Initial application component | `ComponentSupport` | Declarative; internally creates a `ComponentContainer` and automatically loads the referenced component |
Navigation-based component creation | Routing definition in `manifest.json` | Versatile declarative defintion of navigation targets; allows for seamless nesting of components. This approach is especially important when routing is used within nested components, as it prevents conflicts that could arise when multiple components react to the same browser hash change. |
Nested/reuse components | `ComponentContainer` with `usage` | Required for rendering a component; allows for automatic lifecycle management. Nested components can use their own routing to create further nested components \(see navigation-based component creation\). |
Programmatic *reuse* component creation | `Component#createComponent()` | Asynchronous factory; allows to manually orchestrate the loading of a nested reuse component defined in the respective component instance's `manifest.json` \(via `sap.ui5/componentUsages`\). The newly created component is automatically marked as owned by its parent component, which allows for additional manifest-driven extensions. |
Programmatic component creation | `Component.create()` | Asynchronous factory; allows to manually orchestrate the loading |
Caution:
Do not use deprecated legacy mechanisms! For completeness, we mention the deprecated
sap.ui.component()
synchronous factory function. We strongly advise against using this function.
The modern approaches offers several significant advantages:
The following sections outline the recommended ways for instantiating the initial application component. For a detailed guide on creating nested components and subdividing your application, see Nesting Components.
ComponentSupport
- Declarative ApproachThe ComponentSupport
module enables declarative component instantiation directly in HTML, making it the recommended approach for initial application components.
Good to know:
data-handle-validation
for handleValidation
.ComponentSupport
enforces manifest-first loading and asynchronous behavior by default.Container
. See sap.ui.core.ComponentLifecycle
and the section about ComponentContainer
s below.For samples regarding the ComponentSupport
, see Declarative API for Initial Components.
Setup and Usage
Enable ComponentSupport
in your bootstrap:
<!-- index.html -->
<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-on-init="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-resource-roots='{ "my.app": "./" }'
data-...="...">
</script>
You now can declaratively define components directly in HTML using data attributes on a container DOM element (in this sample a <div>
element):
<!-- index.html -->
<body id="content" class="sapUiBody sapUiSizeCompact" role="application">
<div data-sap-ui-component
data-id="myRootComponentContainer"
data-name="my.app"
data-height="100%"
data-settings='{ "id": "myRootComponent" }'
data-handle-validation="true"
data-...="...">
</div>
</body>
For more information, see the API Reference: module:sap/ui/core/ComponentSupport
.
Advanced Usage
For scenarios requiring a pre-initialization setup, you can use a dedicated init
module and manually load the ComponentSupport
. Once loaded, it automatically detects any declarative component definition in the HTML page’s DOM (see the sample above).
<script id="sap-ui-bootstrap"
data-sap-ui-on-init="module:my/app/startupEfforts"
...>
</script>
// my/app/startupEfforts.js
sap.ui.define(["my/app/MyModule"], (MyModule) => {
"use strict";
// Execute prerequisite code, e.g. loading additional application data, connecting to back-end services, etc.
MyModule.init().then(() =>
sap.ui.require(["sap/ui/core/ComponentSupport"])
);
});
ComponentContainer
- Programmatic ApproachSometimes you need to programmatically create a component and render it in a specific part of the application or HTML page. For these use cases, we provide a ComponentContainer
control, which has a special component
association that holds the reference to the component instance.
Note:
You cannot use
placeAt()
directly on components - they must always be wrapped in aComponentContainer
.
ComponentContainer
s offer several features:
onBeforeRendering
, onAfterRendering
) to their associated component.ComponentContainer
has no parent control. The Component#getParent()
function returns null
, even though the ComponentContainer
itself is aggregated in the control tree.propagateModel
property to true
forwards models and binding contexts to the associated component. By default, a component within a ComponentContainer
doesn’t participate in the model propagation process.Using ComponentContainer
s
Method 1: Container-managed component creation
// "ComponentContainer" required from module "sap/ui/core/ComponentContainer"
var oContainer = new ComponentContainer({
name: "samples.components.sample",
manifest: true
});
oContainer.placeAt("target");
Method 2: Pre-created component association
// "Component" required from module "sap/ui/core/Component"
// "ComponentContainer" required from module "sap/ui/core/ComponentContainer"
Component.create({
name: "samples.components.sample",
}).then(function(oComponent) {
// Note: the Component instance (oComponent) is only associated in the ComponentContainer, not aggregated!
var oContainer = new ComponentContainer({
component: oComponent
});
oContainer.placeAt("target");
});
Lifecycle Management
The ComponentContainer
lets you define a lifecycle
of a component and how it aligns with the lifecylce of the container.For more information, see the API Reference: sap.ui.core.ComponentLifecycle
.
Note:
The default is
sap.ui.core.ComponentLifecycle.Legacy
.
// "ComponentContainer" required from module "sap/ui/core/ComponentContainer"
// "coreLibrary" required from module "sap/ui/core/library"
var oContainer = new ComponentContainer({
name: "samples.components.sample",
lifecycle: coreLibrary.ComponentLifecycle.Container,
manifest: true
});
Nesting components lets you subdivide your application into smaller, independent parts. Each part has its own dedicated set of dependencies and resources. For example, in a shop application that displays a list of products, the editing functionality should only be visible to administrators. It doesn’t need to be loaded for other users. Nested components help you decouple this functionality. This approach reduces the initial payload needed to start your main component, improving application startup performance and resource utilization.
You can nest components in these ways:
Component
type. This method is recommended for most use cases. Use it when nested components have routing enabled. It’s crucial when routing is used within nested components, as it prevents conflicts that could arise when multiple components react to the same browser hash change.sap.ui5/componentUsages
section of your parent component’s manifest.json
and creating it using a factory function.Before configuring nested components via routing or instantiating them programmatically, declare them in the sap.ui5/componentUsages
section of your parent component’s manifest.json
:
{
"sap.ui5": {
"componentUsages": {
"myreuse": {
"name": "sap.reuse.component",
"settings": {},
"componentData": {},
"lazy": false
}
}
}
}
Configuration Options:
name
: Component identifier (mandatory)settings
: Component-specific settingscomponentData
: Data passed to the component’s constructorlazy
: Controls the preloading behavior (false
= preload, true
= load on demand)Nesting components with target-based navigation is the recommended way to achieve a separation of concerns. This approach is especially important when routing is used within nested components, as it prevents conflicts that could arise when multiple components react to the same browser hash change.
Using routing with nested components requires:
componentUsages
declarationFor more information, see Enabling Routing in Nested Components.
Routing Configuration (manifest.json
):
type: "Component"
: Indicates that the framework’s routing should instantiate a componentusage
: References the key from componentUsages
in the manifest.json
options
: Additional options for the component. This object merges with the corresponding object from the componentUsages
section of the manifest.json
.containerOptions
: Additional options passed to the ComponentContainer
’s constructorNote:
The routing configuration also provides a
"View"
target type.When multiple components have their own routing configuration, their individual routers coordinate hash access to prevent conflicts. This allows for sub-routing and ensures deterministic navigation across the component hierarchy.
For more information, see Routing Configuration.
{
"sap.ui5": {
"componentUsages": {
"myreuse": {
"name": "reuse.component",
"lazy": false
}
},
"routing": {
"config": {
"async": true
},
"routes": [{
"name": "componentRoute",
"pattern": "component",
"target": "componentTarget"
}],
"targets": {
"componentTarget": {
"type": "Component",
"usage": "myreuse",
"options": {
// Additional component options
},
"containerOptions": {
// ComponentContainer options
}
}
}
}
}
}
In certain scenarios, programmatic component instantiation is required, such as opening a dialog component when a user performs a specific action. The Component
class provides a factory function to asynchronously create reuse components that are declared in the manifest. While this approach requires additional application code, it offers greater control and flexibility, allowing you to precisely orchestrate the loading and instantiation of nested components.
Simplified usage:
const oComponent = await this.createComponent("myreuse");
Extended usage:
const oComponent = await this.createComponent({
usage: "myreuse",
settings: {},
componentData: {}
});
Adding the component to the control tree:
To add your newly created component into the control tree, you need to associate it with a ComponentContainer
:
// associate the component in a ComponentContainer
const oContainer = new ComponentContainer({
component: oComponent
});
// and place it into the control tree
myView.addContent(oContainer);
ComponentContainer
with owner component:
Instead of calling the Component#createComponent
factory on a component instance, you can directly create a ComponentContainer
and reference the reuse component via its name declared in the manifest.json
.
This approach only works if you ensure that the ComponentContainer
is instantiated within the “owner scope” of the component defining the componentUsage
. For more information, see The Owner Component.
For more information, see the usage
options outlined in the API Reference for ComponentContainer
and the API Reference for Component#runAsOwner
used in the example below.
// Ensure that the ComponentContainer is created in the correct owner scope!
oMyAppComponent.runAsOwner(() => {
const oContainer = new ComponentContainer({
usage: "myreuse"
})
oContainer.placeAt("target");
})
To declaratively create a component from within an XML view, simply place it in the XML DOM:
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" ...>
<core:ComponentContainer usage="myreuse" manifest="true" />
</mvc:View>
Note:
Depending on how you create the XML view, you may need to ensure that the owner scope is correctly set. For more information, see The Owner Component.
If your view is created programmatically and not via a routing target, you need to wrap the view’s factory call in a corresponding Component#runAsOwner
call:
oMyAppComponent.runAsOwner(() => {
const oMyView = await XMLView.create(...);
// add the view to the control tree
});
The OpenUI5 framework is continuously evolving to leverage modern web standards and browser capabilities while maintaining backward compatibility. To keep your applications performant, secure, and future-ready, migrating from legacy component APIs to modern alternatives is essential.
Note:
For comprehensive guidance on modernizing your codebase, see Best Practices for Developers, which provides detailed recommendations for legacy-free OpenUI5 development.
sap.ui.component()
FactoryThe legacy sap.ui.component()
factory function creates components synchronously, which blocks the UI thread and violates Content Security Policy requirements. Migrating to asynchronous alternatives is essential for modern OpenUI5 development.
Legacy approach:
createContent: function() {
var oReuseComponent = sap.ui.component({
"name": "sap.reuse.component"
});
}
Modern approach:
createContent: function() {
var oReuseComponentPromise = this.createComponent({
"usage": "reuse"
});
}
Legacy definition in manifest.json:
{
"sap.ui5": {
"dependencies": {
"components": {
"sap.reuse.component": {}
}
}
}
}
Modern definition in manifest.json:
{
"sap.ui5": {
"componentUsages": {
"reuse": {
"name": "sap.reuse.component",
"lazy": false
}
}
}
}
Component.create()
instead of sap.ui.component()
.ComponentSupport
for initial components over manual ComponentContainer
creation.componentUsages
rather than in dependencies
.ComponentContainer
’s lifecycle
property.Related Information
Declarative API for Initial Components
Enabling Routing in Nested Components
Descriptor Dependencies to Libraries and Components
API Reference: sap.ui.core.Component