I am working on a SAPUI5 application. I have an XML view which contains an XML Fragment and a Button to save.
The fragment contains a few controls like drop-down, text field and a table. When I press on the save button, I need to get all the rows in the table and call an OData update service.
The problem is in the onSave
method in view controller. I get an error while accessing the table using its ID. Can anyone help me and advice how can I access controls used in fragments by their ID in the controller?
Here is the code snippet:
View:
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" xmlns:form="sap.ui.layout.form" xmlns="sap.m">
<Page>
...
<form:SimpleForm>
<core:Fragment id ="fr1" fragmentName="first" type="XML" />
<Button id="id1" press="onSave" />
</form:SimpleForm>
</Page>
</mvc:View>
Fragment definition:
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
<Table id="tab1" mode="MultiSelect">
...
</Table>
</core:FragmentDefinition>
Controller:
sap.ui.controller("view", {
onSave: function() {
//var tab = this.getView().byId("tab1"); // Not working
var tab = sap.ui.getCore().byId("tab1"); // Not working
},
// ...
});
Accessing controls inside a fragment depends on how your fragment was created in the first place. Here is a list of cases with respective API to use to get the control reference:
this.byId("controlId");
When the fragment was created with a view ID:
sap.ui.xmlfragment(this.getView().getId(), "my.Fragment", this); // deprecated *
<core:Fragment fragmentName="my.Fragment" type="XML" />
<!-- Here, the view ID will be automatically passed to the fragment -->
Global ID: "componentId---viewId--controlId"
**
this.byId(Fragment.createId("fragmentId", "controlId"));
When the view ID and a fragment ID were given:
sap.ui.xmlfragment(this.createId("fragmentId"), "my.Fragment", this); // deprecated *
<core:Fragment id="fragmentId" fragmentName="my.Fragment" type="XML"/>
Global ID: "componentId---viewId--fragmentId--controlId"
**
Fragment.byId("fragmentId", "controlId");
When fragment ID only:
sap.ui.xmlfragment("fragmentId", "my.Fragment", this); // deprecated *
Global ID: "fragmentId--controlId"
sap.ui.getCore().byId("controlId");
When no IDs were given:
sap.ui.xmlfragment("my.Fragment", this); // deprecated *
// All control IDs within the fragment gets registered globally without any prefixes!!
Global ID: "controlId"
document.getElementById(a) // Only for native <html:...> elements within the fragment
a
corresponds to this.createId("elementId")
, Fragment.createId("fragmentId", "elementId")
, or just "elementId"
depending on how the fragment was created as described above.*: The API sap.ui.*fragment
is deprecated. Use Fragment.load
instead (available since 1.58).
**: The component ID won't be a part of the global ID if no stable ID was given for the view. In that case, the global ID starts with the generated view ID: "__xmlview0--..."
.
this
: Reference to the controller instanceFragment
: Parameter name for the resolved module given by the dependency definition
sap.ui.define([ // or .require
"sap/ui/core/Fragment",
// ...
], function(Fragment, /*...*/) { /*...*/});
Avoid concatenating ID parts or relying on the syntax of the global ID, as mentioned in the comment as well as in the documentation:
Do not rely on the specific prefixing syntax because it may change at some point. Always use methods like
byId()
andcreateId()
.
myManuallyAccessedInput.setValue("...")
). Make use of data binding instead ⇒ Changes in model will be reflected in UI automatically.