Skip to Content
avatar image
Former Member

Editing Items on Fiori ListReport Template

We need to be able to edit some fields for each item in the report, without having to navigate to the detail page to do it. I am assuming that if the ODataModel is TwoWay and the ui.table.Table has been configured as editable, then the fields will be turned to editable controls when the Edit button is pressed, based on the sap:updatable attributes in the metadata.xml.

The issues:
- We are not getting the Edit button at the top of the table.
- If I set the ui.table to Editable in the controller, then all the fields become editable, not just those with the corresponding updatable attribute.

I'd appreciate it if someone can point me into the right direction to get the Edit mode going on the list report.

SAPui5 V1.38.5

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

1 Answer

  • avatar image
    Former Member
    Jun 28, 2017 at 10:34 PM

    Setting the table to edit caused all the fields to become editable, instead of only the fields that have the configuration: sap:updatable="true",
    and there were no Edit, Save or Cancel buttons. Using the "Edit Togglable" property in the UI Adaptation Editor had no effect in the ListReport.

    I implemented this manually, this is how I tackled this issue:

    The updatable attribute was configured for the EntitySet and for various Properties in the EntitySet.
    The Edit button was only available in the detail page but we didn't want the edit button displayed on the detail page, so I created a Controller extension for the ObjectPage in the manifest:

    "sap.suite.ui.generic.template.ObjectPage.view.Details": {
    	"controllerName": "MY_NAMESPACE.ext.controller.ObjectPageController"

    and inside the controller, removed the edit control from the interface:

    var oEditBtn = this.getView().byId(this._sCtrlId + "edit");
    if (oEditBtn) {

    I added an Edit button to the ListReport by including Actions in the manifest, along with the Save and Cancel buttons:

    "Actions": {
    	"EditItems": {
    		"id": "EditActionId",
    		"text": "{{LBL_EDIT}}",			
    		"press": "onEditPressed",
    		"requiresSelection": false,
    		"determining": false
    	"SaveItems": {
    		"id": "SaveEditActionId",
    		"text": "{{LBL_SAVE}}",			
    		"press": "onSavePressed",
    		"determining": true
    	"CancelItems": {
    		"id": "CancelEditActionId",
    		"text": "{{LBL_CANCEL}}",			
    		"press": "onCancelPressed",
    		"determining": true

    According to the documentation, setting one of these Actions with "determining": true should render the control on the footer of the application, however in this version (1.38.5) this did not occur. The Save and Cancel buttons remained on the header, along with the Edit button.
    To handle this I had to hide/show these buttons depending on the state of the application.

    Now I had to implement the edit feature, when the user press on the Edit button, the application goes into edit state.
    To ensure the edited items won't disappear from the screen, I disabled all the filters in the FilterBar along with the Go button.
    Hide the Edit button and show the Save and Cancel buttons. I clear the messages and show a message popover button, so that the user will have some feedback regarding edits.

    And then I built a set of templates for the fields/columns. This was the fun part, using the service metadata I inspect all the properties of the EntitySet to discover all updatable fields:

    var oMeta = this._oSmartTable.getModel().getServiceMetadata();	
    for (var iSchema in oMeta.dataServices.schema) {
    	for (var iEntityType in oMeta.dataServices.schema[iSchema].entityType) {
    		if (oMeta.dataServices.schema[iSchema].entityType[iEntityType].name === "MyEntity") {
    			this._oEntitySchema = oMeta.dataServices.schema[iSchema].entityType[iEntityType];
    	if (this._oEntitySchema) {

    Based on the field's data-type I created a suitable control that will be set as the template for the column in the table.

    for (var iProp in {
    	var bUpdatable = true;
    	var sLabel = "";
    	for (var iUpdatable in[iProp].extensions) {
    		if ([iProp].extensions[iUpdatable].name === "label") {
    			sLabel =[iProp].extensions[iUpdatable].value;
    		if ([iProp].extensions[iUpdatable].name === "updatable" &&[iProp].extensions[iUpdatable].value === "false") {
    			bUpdatable = false;
    	if (bUpdatable === true) {	
    		var sName =[iProp].name;
    			var sType =[iProp].type;
    			var oControlTemplate = null;
    			switch (sType) {			
    				...	// Edm.Decimal, Edm.DateTime, ...

    Now, our users expected that all the text in each control is selected/highlighted when the input has focus, and we had some additional requirements for some of the fields: minimum values, date and number validations, and there was a read-only field that had to be updated when a price value was updated. So I added some event handlers to the controls while I created the templates to handle these requirements.

    The ui.table.Table, unlike the m.Table did not have the very useful setKeyboardMode() method, so I had to add key listeners to these controls and handle the Tab, Shift+Tab, Up, and Down arrow keys to manage navigation from one input to the next.

    oControlTemplate.attachBrowserEvent("keydown", this._handleEditNavigationKey, this);

    I managed this navigation by inspecting the Table's Rows and Cells, placing focus on the next/previous editable control.

    I had some issues with the ODataModel when updating the changes: When using batch, and an edit failed on one item, all the updates in the batch failed, so each item had to be updated individually. submitChanges() documentation mentions: "Important: The success/error handler will only be called if batch support is enabled." So when updating individual edits not using batch I received no response for success/error and was not able to handle the messages I tried both attachBatchRequestSent and setting the sucess/error callbacks in the oParameters for the submitChanges and update calls.

    So I handled this manually... I recorded each edit in an array. Storing the sPath, the propertyName, the new value and old value and data-type. When multiple edits were made on a field, I just updated the new value and if a value became the same as the original value I removed the field's entry in the edits array.

    When the user hit the Save button, I use this array to send the updates. I create a new ODataModel and set it to use batch. Then for each item in the edits list, I called the update() method and was able to handle the success/error results for individual items.

    If the user press Cancel I reset the changes, using the sPath stored in the edits list and use the main model's resetChanges() method. Making sure that read-only field's value gets reset correctly.

    Mass Edit.
    I handled the mass editing in a dialog. So I created a new fragement "MassEditDialog" to act as my dialog.
    I wrote two custom controls, a RadioButton extension that has an input control next to it, (Number, Text, ComboBox or DatePicker) instead of the label, and a RadioButtonGroup to hold these custom RadioButtons.
    Then I created another fragment "FieldEditor" which contained a VBox and inserted a custom RadioButton with a ComboBox so that I can show some predefined values and the "< Keep Existing Values >" item (set as default selection).

    When the dialog launches, I create a FieldEditor for each of the updatable fields.
    I look at the table's selected items values, and add the first 10 unique values into the FieldEditor's first ComboBox.
    Again using the metadata that I gathered earlier to specify the control type, I insert another custom RadioButton in the VBox to allow the user to specify a unique value.

    I'd appreciate some feedback regarding these:

    I was not sure where to put the trigger for the Mass Edit feature, so I added a "Mass Edit" Menu-Item in the editable Columns menu's.

    I had some issues with the Custom RadioButton controls. I wanted to set it selected when the added input control receives input focus. But didn't manage to do this, so settled to have it set as selected when the input control's value changes, or when the user clicks on the RadioButton's dot.

    Also, when the table's "Select All" check box is pressed, for mass editing I have get all the records.
    I had to set the table's threshold to the model's "count" of the current filtered-selection and execute a "rebindTable" to ensure that everything is loaded for the mass edit.

    I would have preferred it if the smart controls managed this for me, I was just not able to get it going. And had to do a fair amount to enable editing on the list report. Hopefully this will help anyone that is in the same boat.

    Add comment
    10|10000 characters needed characters exceeded