Skip to content

Latest commit

 

History

History
482 lines (331 loc) · 14.2 KB

stable-ids-all-you-need-to-know-f51dbb7.md

File metadata and controls

482 lines (331 loc) · 14.2 KB

Stable IDs: All You Need to Know

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 and do not have any auto-generated parts.

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:

  • Automated tests

    To check the behavior of apps at runtime, these tests find controls by searching for stable IDs. If you use OPA in OpenUI5, you're able to find controls via other criteria like control type, display name and others. For more information, see Integration Testing with One Page Acceptance Tests (OPA5).

  • Inline help tools

    These tools display user assistance information directly in the app and depend on stable IDs (example: SAP Companion).

Tip:

Stable IDs are an important prerequisite for SAPUI5 flexibility services, automated testing, and inline help tools. Apps with stable IDs are of high quality and offer customers more functionality. Therefore, 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.

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 and Manifest (Descriptor for Applications, Components, and Libraries).

    Example:

    "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:

    <mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
    	<Page id="myPage">
    		<mvc:XMLView id="myEmbeddedView" viewName="MyView" async="true" />
    	</Page>
    </mvc:View>
    
  • 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 method of the owner component.

    Example:

    // 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.

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. For more information, see Support for Unique IDs.

    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:

    <mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
    	<Page id="myPage">
    			<Table id="myTable">
    			</Table>
    	</Page>
    </mvc:View>
  • Programmatic creation

    For JavaScript views and JavaScript-generated controls, you must use the createId method of the View, Controller, or UIComponent. Here's how it could look like when you're creating a control directly in the controller code:

    // 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):

<head>
	<!-- ... -->
	<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>
</head>
<body class="sapUiBody sapUiSizeCompact">
	<div data-sap-ui-component
		data-id="myRootComponentContainer"
		data-name="my.app"
		data-settings='{ "id": "myRootAppComponent" }'
		data-height="100%"
	></div>
</body>

For more information, see sap/ui/core/ComponentSupport.

Alternatively, when creating a ComponentContainer manually:

// 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.

"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 call or within the settings property of the ComponentContainer, as shown below.

<core:ComponentContainer xmlns:core="sap.ui.core"
	id="myEmbeddedComponentContainer"
	autoPrefixId="true"
	settings='{ "id": "myEmbeddedComponent" }'
	usage="myReuseComponent"
	manifest="true"
	height="100%"
	lifecycle="Container"
/>

For more information on embedded components, see Using and Nesting Components and Enabling Routing in Nested Components.

Alternatively, you could use the 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 API.

Example using the controller function loadFragment:

// 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:

// 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) => {
	// ...
});

Note:

You can also define individual IDs (and prefixes) for each instance of a fragment.

// 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) => {
	// ...
});
<!-- When embedding a fragment declaratively, you can specify a stable prefix ID on the XML node itself -->
<core:Fragment xmlns:core="sap.ui.core"
	id="myFragment1"
	fragmentName="my.app.view.SampleFragment"
	type="XML"
/>

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"

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] + [Alt] /[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.

Related Information

Support Assistant