docs

ID Handling in OpenUI5: The Complete Guide

This guide covers everything you need to know about ID handling in OpenUI5, from stable IDs for controls and components to DOM element IDs and how the framework manages them. Understanding ID handling is essential for building maintainable, testable, and adaptable applications.

On this page:


Overview: ID Types in OpenUI5

OpenUI5 uses several types of IDs throughout its architecture:

Each type serves a different purpose but they are all interconnected. When you set a stable control ID, it influences the DOM element ID that gets generated when the control is rendered.


Stable IDs: What They Are and Why They Matter

Stable IDs are IDs for controls, elements, or components that you set yourself in the respective id property or attribute, as opposed to IDs that are generated by OpenUI5. Stable means that the IDs are concatenated with the application component ID, do not have any auto-generated parts, and remain consistent across different application startups.


Background: Generated vs. Stable IDs

If you don’t define IDs, OpenUI5 generates them dynamically. These IDs are not static and might differ from program run to program run. For example, the page and table in the following XML view could have the generated IDs "__page0" and "__table0" at runtime:

<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
    <Page>
        <Table>
        </Table>
    </Page>
</mvc:View>

The generated IDs change whenever the control structure of the app changes. The sequence of instantiation also plays a role: If there are two views with unstable IDs in the app, depending on the order the views are opened, they get the generated IDs "__view0" and "__view1". This is an issue for the following features that require stable IDs:

Tip:

As stable IDs are an important prerequisite for SAPUI5 flexibility services, automated testing, and inline help tools, we strongly recommend that you use stable IDs whenever possible (some technical controls don’t need stable IDs, such as CustomData).

Caution:

If some controls have disappeared after a software upgrade or the way in which they can be identified has been changed, this has a direct impact on the functions that depend on stable IDs. These stable IDs are part of the public API of the app, and therefore must be kept stable over the life cycle of the app.

Do not delete any control that has a stable ID. If you need to remove a control from an app, set the control’s visible property to false.


Understanding ID Structure and Prefixing

OpenUI5 uses a hierarchical ID structure that combines component, view, and control IDs into a single concatenated string. Understanding this structure helps you predict runtime IDs and debug issues effectively.


The ID Hierarchy

When a control is rendered, its ID is composed of multiple parts:

  1. Component ID: The outermost prefix, set when instantiating the component
  2. View ID: Added as a prefix to controls within the view
  3. Fragment ID (optional): Added when controls come from fragments
  4. Control ID: The ID you define in the control’s id property

These parts are joined together using specific separators:

For example, a button with ID "myButton" in a view with ID "mainView" inside a component with ID "myApp" has the runtime ID "myApp---mainView--myButton".

Note:

Do not rely on the specific prefixing syntax because it may change at some point. Always use methods like byId() and createId() to work with IDs programmatically.


The createId() and byId() Methods

OpenUI5 provides helper methods to work with prefixed IDs:

// In a controller, get a control from the view
var oTable = this.byId("myTable");

// Create a prefixed ID for a new control
var sNewId = this.createId("dynamicButton");

How to Set IDs Manually to Keep Them Stable

Tip:

Using the rule Stable control IDs are required for SAPUI5 flexibility services in the Support Assistant, you can check whether all controls use stable IDs. For more information, see How to Check If All Your IDs Are Stable.

**Views** - **Views in the manifest:** The standard use case is that you use stable IDs for the view that the router navigates to. Ideally, instead of creating the views yourself, you create them with routing targets and declare the view ID in the manifest.json file as shown in the example below. For more information, see [Routing and Navigation](/docs/04_Essentials/routing-and-navigation-3d18f20.html) and [Manifest \(Descriptor for Applications, Components, and Libraries\)](/docs/04_Essentials/manifest-descriptor-for-applications-components-and-libraries-be0cf40.html). Example: ```json "sap.ui5": { "rootView": { "id": "myRootView", "viewName": "my.app.view.Root", "...": "..." }, "routing": { "targets": { "myTarget": { "id": "myView", "name": "MyView", "...": "..." } } } } ``` - **Embedded views:** If you embed your view, set its ID. Example: ```xml ``` For more information, see [IDs in Nested and Reused Views](/docs/05_Developing_Apps/id-handling-in-openui5-the-complete-guide-f51dbb7.html#loiof51dbb78e7d5448e838cdc04bdf65403__section_NRUV). - **Programmatic creation:** If you create the view programmatically, provide the ID as one of the parameters to the factory function. Make sure to prefix the view ID with the component ID using the [`createId`](https://ui5.sap.com/#/api/sap.ui.core.UIComponent/methods/createId) method of the owner component. Example: ```js // XMLView required from "sap/ui/core/mvc/XMLView" myOwnerComponent.runAsOwner(() => XMLView.create({ id: myOwnerComponent.createId("myProgrammaticView"), viewName: "my.app.view.ProgrammaticView" })).then((createdView) => { // ... }); ``` For more information, see [Views](/docs/04_Essentials/views-91f27e3.html). > ### Caution: > Do **not** specify the ID of an XML view directly in the XML definition itself \(<mvc:View id="...">\). Doing so will prevent multiple instances of the same declarative view from being created, and you will see "FUTURE FATAL" error logs when an ID is given in the XML.
**Extension points** If you use extension points, use stable IDs for nested views and prefixes for nested controls of a fragment.
**Controls** - **Controls in XML views:** The XML view prefixes the control IDs \(only the defined IDs, not the automatically created ones\) with its own ID. This allows you to use the same control ID for different views and the same view multiple times. If the following XML view is instantiated using the ID `"myView"`, the contained page and table would have the IDs `"myView--myPage"` and `"myView--myTable"` at runtime: ```xml
``` - **Programmatic creation:** For JavaScript views and JavaScript-generated controls, you must use the `createId` method of the [`View`](https://ui5.sap.com/#/api/sap.ui.core.mvc.View/methods/createId), [`Controller`](https://ui5.sap.com/#/api/sap.ui.core.mvc.Controller/methods/createId), or [`UIComponent`](https://ui5.sap.com/#/api/sap.ui.core.UIComponent/methods/createId). Here's how it could look like when you're creating a control directly in the controller code: ```js // Button required from "sap/m/Button" // this == Controller instance new Button({ id: this.createId("myButton"), // ... }); ```
**Components** > ### Note: > The following is only relevant if you do not use the SAP Fiori launchpad because it instantiates components for you and provides IDs. If you instantiate a component inside an HTML page, set the ID of the component as shown below. To get unique IDs for the views and controls inside the component, they must be prefixed with the component ID. All views in the component that are created by the framework are automatically prefixed with the component ID. Examples \(Standalone App scenario\): ```html
``` For more information, see [`sap/ui/core/ComponentSupport`](https://ui5.sap.com/#/api/module:sap/ui/core/ComponentSupport). Alternatively, when creating a `ComponentContainer` manually: ```js // ComponentContainer required from "sap/ui/core/ComponentContainer" new ComponentContainer({ id: "myRootAppComponentContainer", autoPrefixId: true, name: "my.app", manifest: true, settings: { // Component settings id: "myRootAppComponent" }, height: "100%" }).placeAt("content"); ```
**Embedded Components** Let's say you want to embed a component with the package name `my.embedded`. You define it as follows in the manifest and use the registered `componentUsages` entry in `ComponentContainer` settings, for example. ```json "sap.ui5": { "componentUsages": { "myReuseComponent": { "name": "my.embedded", "lazy": false } } } ``` > ### Note: > While the `componentUsages` configuration technically allows defining a component ID via `settings: { id: "..." }` directly in manifest.json, doing so can lead to ID conflicts at runtime when the framework instantiates the target `Component` **more than once** through the same `componentUsages` configuration. To avoid this, the component `id` can be specified in the [`Component#createComponent`](https://ui5.sap.com/#/api/sap.ui.core.Component%23methods/createComponent) call or within the `settings` property of the `ComponentContainer`, as shown below. ```xml ``` For more information on embedded components, see [Component Instantiation Guide](/docs/04_Essentials/component-instantiation-guide-346599f.html) and [Enabling Routing in Nested Components](/docs/04_Essentials/enabling-routing-in-nested-components-fb19f50.html). Alternatively, you could use the [`sap/ui/core/Component.create`](https://ui5.sap.com/#/api/sap.ui.core.Component/methods/sap.ui.core.Component.create) API and specify the `id` in the arguments. > ### Note: > In order to support SAPUI5 flexibility features, all embedded components should have a stable ID.
**XML fragments** If you use XML fragments in your app, make sure they are instantiated with the correct view ID prefix. To simplify this, you can use the [`sap/ui/core/mvc/Controller.loadFragment`](https://ui5.sap.com/#/api/sap.ui.core.mvc.Controller%23methods/loadFragment) API. Example using the controller function `loadFragment`: ```js // this == Controller instance this.loadFragment({ // id: view ID as prefix by default name: "my.app.view.SampleFragment" }); ``` Alternatively, when using the generic function `sap/ui/core/Fragment.load` manually: ```js // Fragment required from sap/ui/core/Fragment // this == Controller instance this.getOwnerComponent().runAsOwner(() => Fragment.load({ id: this.getView().getId(), // view ID as prefix needed name: "my.app.view.SampleFragment", controller: this })).then((createdFragment) => { // ... }); ``` You can also define individual IDs \(and prefixes\) for each instance of a fragment. ```js // Here we deactivate the default prefixing and pass a custom ID for the fragment instance this.loadFragment({ id: this.createId("myFragment1"), autoPrefixId: false, name: "my.app.view.SampleFragment" }); // or via generic factory: this.getOwnerComponent().runAsOwner(() => Fragment.load({ id: this.createId("myFragment1"), name: "my.app.view.SampleFragment", controller: this })).then((createdFragment) => { // ... }); ``` ```xml ```

How to Name Stable IDs

Choose names for your stable IDs that describe the semantics of your views and controls, such as page or table.

Note:

For the allowed sequence of characters, see the namespace sap.ui.core.ID. But bear in mind not to use hyphens (-) as separators in your names as they would interfere with the ones that are added automatically by the framework.

Example:

Let’s say you’re building an app with the component ID "myProducts". You’re using stable IDs for the views and contained views. Here’s what the concatenated IDs that are generated at runtime look like:

Component Views Contained Views Concatenated IDs
`"myProducts"` `"worklist"` `"page"` `"myProducts---worklist--page"`
`"table"` `"myProducts---worklist--table"`
`"product"` `"page"` `"myProducts---product--page"`
`objectHeader` `"myProducts---product--objectHeader"`

How to Check If All Your IDs Are Stable

With the Support Assistant, you can analyze whether there are any issues with the stable IDs used in your app. Here’s how you can check this:

  1. Open your app in a browser.
  2. Enter the shortcut [Ctrl] + [Shift] + [left Alt / left Option] + [P] to start the Support Assistant.
  3. In the Technical Information Dialog, choose Activate Support Assistant.
  4. In the table on the left, deselect all rules.
  5. Click on the Rules column.
  6. Filter for stable and choose Enter.
  7. Select the Stable control IDs are required for SAPUI5 flexibility services rule.
  8. Choose Analyze.

If any generated IDs are found, set the IDs for these controls manually as described here.


IDs in Nested and Reused Views

When you reuse or nest views, the stable IDs you define are no longer unique on their own. To avoid ambiguity, each view automatically adds its own ID as a prefix to all of its child controls.

Consider a child view (MyEmbeddedButtonView.view.xml) that contains a button with the stable ID "myButton":

<!-- View Name: my.app.view.MyEmbeddedButtonView -->
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
  <Button id="myButton" text="Click Me" />
</mvc:View>

Now, embed this view multiple times in MyContainerView.view.xml:

<!-- View Name: my.app.view.MyContainerView -->
<mvc:View xmlns:mvc="sap.ui.core.mvc">
  <mvc:XMLView id="myEmbeddedButtonView1" viewName="my.app.view.MyEmbeddedButtonView" />
  <mvc:XMLView id="myEmbeddedButtonView2" viewName="my.app.view.MyEmbeddedButtonView" />
</mvc:View>

At runtime, if the container view has the ID myContainerView, the IDs resolve as follows:

Element Runtime ID
First embedded view `myContainerView--myEmbeddedButtonView1`
Second embedded view `myContainerView--myEmbeddedButtonView2`
Button in first view `myContainerView--myEmbeddedButtonView1--myButton`
Button in second view `myContainerView--myEmbeddedButtonView2--myButton`

To access controls in nested views (e.g. myEmbeddedButtonView1), chain the byId() calls:

const myEmbeddedButton = oContainerView.byId("myEmbeddedButtonView1")?.byId("myButton");

If you create additional controls during runtime in JavaScript, the controller provides the createId() method to create unique, prefixed IDs automatically.


IDs in Fragments

Fragments are lightweight, reusable UI parts that require special attention for ID handling. Unlike views, fragments don’t have their own controller or lifecycle, which means they handle IDs differently. By default, stable IDs in fragments are used as-is, without automatic prefixing—unless you explicitly provide a fragment ID during instantiation.


The Basics: Fragment ID Prefixing

All IDs given as static strings inside declarative views are automatically prefixed with the view ID. Fragments, however, are meant to be more lightweight. For this reason, the following applies:


IDs in Declarative Fragments (XML)

Consider this XML fragment example:

<HBox xmlns="sap.m">
    <Button text="Hello World" />
    <Button id="btnInFragment" text="Hello World" />
</HBox>

The first button always has a generated ID (like __button2), regardless of how the fragment is instantiated. The second button’s ID depends on whether you provide a fragment ID:

Without fragment ID (risk of duplicate ID errors if used twice):

sap.ui.require(["sap/ui/core/Fragment"], function(Fragment){
    Fragment.load({
        name: "my.useful.UiPartZ"
    }).then(function(oFragment){
        // ...
    });
    // Button ID will be "btnInFragment" - no prefix!
    // Instantiating the same Fragment twice will result in a runtime error, since the ID is already in use.
    // To prevent this, either use a prefix OR destroy the previous instances before creating a new one.
});

With fragment ID:

sap.ui.require(["sap/ui/core/Fragment"], function(Fragment){
    Fragment.load({
        name: "my.useful.UiPartZ",
        id: "myFragment"
    }).then(function(oFragment){
        // ...
    });
    // Button ID will be "myFragment--btnInFragment"
    // No ID conflict, thus the Fragment can be instantiated twice without issues.
});

IDs in JavaScript-based Fragments

In JavaScript-based fragments, the framework cannot automatically influence control IDs created by the createContent() method. You need to explicitly use this.createId() to enable ID prefixing:

// my/own/MyFragment.js
sap.ui.define(["sap/m/Button"], function (Button) {
    return {
        createContent: function(oController) {
            return [
                // Without createId() - ID won't be prefixed
                // Note: Controls like this are not accessible via their ID as the specific runtime ID is unknown at devtime
                new Button({text: "Button without prefix"}),
                // With createId() - ID will be prefixed if fragment has an ID
                new Button(this.createId("btnInJsFragment"), {
                    text: "Button with prefix"
                })
            ];
        }
    }
});

If an ID is given when the fragment is instantiated, createId() adds it as prefix. Otherwise, createId() leaves the given ID untouched.


Using Fragments in Views

When fragments are used within views, generated IDs (controls without explicit IDs) are not prefixed. For controls with explicit IDs, the following rules apply:

Using the Controller.loadFragment() method (available since OpenUI5 version 1.93) simplifies this—it automatically prefixes fragment content IDs with the view ID:

sap.ui.define(["sap/ui/core/Controller"], function(Controller){
    return Controller.extend({
        onInit: function(){
            // IDs automatically prefixed by view ID
            this.loadFragment({
                name: "my.useful.UiPartZ"
            }).then(function(oFragment){
            // Button ID: "viewId--btnInFragment"
            });

            // With additional fragment ID
            this.loadFragment({
                id: "myFrag",
                name: "my.useful.UiPartZ"
            }).then(function(oFragment){
            // Button ID: "viewId--myFrag--btnInFragment"
            });
        }
    })
});

You can also embed fragments declaratively in XML views:

<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
    <layout:VerticalLayout xmlns:layout="sap.ui.layout">
        <!-- Fragment without ID - control IDs prefixed by view ID only -->
        <core:Fragment fragmentName="module:my/own/MyFragment" />

        <!-- Fragment with ID - control IDs prefixed by view ID + fragment ID -->
        <core:Fragment id="myFrag" fragmentName="module:my/own/MyFragment" />
    </layout:VerticalLayout>
</mvc:View>

Retrieving Controls from Fragments

Due to the prefixing mechanism, you need to use the appropriate method based on your context:

When the fragment is NOT part of a view:

// Fragment required from "sap/ui/core/Fragment"
// Element required from "sap/ui/core/Element"

// Without fragment ID - use the global registry
const myControl = Element.getElementById("myControl");

// With fragment ID "myFrag"
// this internally of course uses Element.getElementById, but takes care of prefixing the fragment ID for you
const myControl = Fragment.byId("myFrag", "myControl");

When the fragment IS embedded in a view (code inside controller):

// Without fragment ID - view's byId handles the prefix
const myControl = this.byId("myControl");

// With fragment ID "myFrag" - combine Fragment.createId with view's byId
const myControl = this.byId(Fragment.createId("myFrag", "myControl"));

Related Information

API Reference: sap.ui.core.mvc.View#createId

API Reference: sap.ui.core.mvc.View#byId

API Reference: sap.ui.core.Fragment#byId

API Reference: sap.ui.core.Fragment#createId

API Reference: sap.ui.core.Element#getElementById

API Reference: sap.ui.core.ID

Support Assistant

Integration Testing with One Page Acceptance Tests (OPA5)