1

I'm building a Room Booking System using SAP Fiori. Here's a requirement I have to implement:

In the page Find Room users will choose a room and a date, then take action onBookRoom. The action will navigate to the page Book Room which uses the template Form Entry Object Page, also passing the parameters DateScheduled and RoomID to this page. The Book Room page will assign these parameters' values to the fields DateScheduled and RoomID in the page.

The navigation worked, the parameters are passed into the Book Room page successfully.

My question is, how can I fill these parameters' values to DateScheduled and RoomID fields in page Book Room in SAP Fiori?

I've searched all over SAP Help forums but found no answer. There's an article which guides how to prefill fields but it performs from the backend, which seems unable to get the navigation parameters.

I'm using VSCode SAP Fiori Extension and OData V4 on backend, running a local Fiori launchpad with Fiori sandbox and NodeJS Express as the frontend server.

The entity bound to page Book Room has these fields:

key ScheduleId,
    DateScheduled,
    RoomId

fioriSandboxConfig.json

        "zmrbsschedule-create": {
          "semanticObject": "zmrbsschedulecreate",
          "action": "create",
          "title": "New Schedule",
          "signature": {
            "parameters": {
              "DateScheduled": {
                "required": false
              },
              "RoomId": {
                "required": false
              }
            },
            "additionalParameters": "allowed"
          },
          "resolutionResult": {
            "applicationType": "URL",
            "additionalInformation": "SAPUI5.Component=zmrbsschedulecreate",
            "url": "./"
          }
        },
        "zavailroom-display": {
          "semanticObject": "zavailroom",
          "action": "display",
          "title": "Find Available Rooms",
          "signature": { "parameters": {}, "additionalParameters": "allowed" },
          "resolutionResult": {
            "applicationType": "URL",
            "additionalInformation": "SAPUI5.Component=zavailroom",
            "url": "./"
          }
        },

ToBookRoom.controller.js (controller extension in page Find Room)

sap.ui.define(['sap/ui/core/mvc/ControllerExtension'], function (ControllerExtension) {
'use strict';

return ControllerExtension.extend('zavailroom.ext.controller.ToBookRoom', {
    // this section allows to extend lifecycle hooks or hooks provided by Fiori elements
    override: {
        /**
         * Called when a controller is instantiated and its View controls (if available) are already created.
         * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
         * @memberOf zavailroom.ext.controller.ToBookRoom
         */
        onInit: function () {
            // you can access the Fiori elements extensionAPI via this.base.getExtensionAPI
            var oModel = this.base.getExtensionAPI().getModel();
        }
        
    },

    onBookRoom: async function () {
        const oAPI = this.base.getExtensionAPI();
        const ctx = oAPI.getBindingContext();
        const roomId = ctx.getProperty("RoomID");
        const dateSche = ctx.getProperty("DateSche");

        // sap.ushell.Container
        const Navigation= await sap.ushell.Container.getServiceAsync("Navigation");

        // trigger navigation
        Navigation.navigate({
            target: { semanticObject: "zmrbsschedulecreate", action: "create" },
            params: {
                RoomId: roomId,
                DateScheduled: dateSche
            }
        });
    }
});

});

CreateScheduleController.controller.js (controller extension in page Book Room)

sap.ui.define(['sap/ui/core/mvc/ControllerExtension'], function (ControllerExtension) {
'use strict';

return ControllerExtension.extend('zmrbsschedulecreate.ext.controller.CreateScheduleController', {
    // this section allows to extend lifecycle hooks or hooks provided by Fiori elements
    override: {
        /**
         * Called when a controller is instantiated and its View controls (if available) are already created.
         * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
         * @memberOf zmrbsschedulecreate.ext.controller.CreateScheduleController
         */
        onInit: function () {
            // you can access the Fiori elements extensionAPI via this.base.getExtensionAPI
            var oModel = this.base.getExtensionAPI().getModel();
        },

        onAfterRendering: async function () {
            console.log("CreateScheduleController loaded");

            const oComponent = this.getView().getController().getAppComponent();
            const oParams = oComponent.getComponentData()?.startupParameters || {};
            console.log("Startup parameters:", oParams);
            console.log("RoomId:", oParams.RoomId);
            console.log("DateScheduled:", oParams.DateScheduled);
            console.log("preferredMode:", oParams.preferredMode);
            
            var oModel = this.base.getExtensionAPI().getModel();
            console.log("Model:", oModel);
            const oContext = this.base.getExtensionAPI().getBindingContext();
            console.log("Context:", oContext);

            if (!oContext) {
                console.warn("No binding context available.");
                return; // no create context yet
            }

            // ---- SET FIELDS HERE ----
            if (oParams.RoomId) {
                oContext.setProperty("RoomId", oParams.RoomId[0]);
            }

            if (oParams.DateScheduled) {
                oContext.setProperty("DateScheduled", oParams.DateScheduled[0]);
            }
        }
    }
});

});

I tried to fill fields DateScheduled and RoomID here, by using setProperty() on the binding context, but the binding context is undefined. The startupParameters does have the parameter values I passed from Find Room. Is this the right way? Or I must prefill fields somewhere else?

1 Answer 1

1

In a Form Entry Object Page (FE OData V4), the create context is only created after routing & binding, not during onAfterRendering. That’s why:

const oContext = this.base.getExtensionAPI().getBindingContext();

Option 1: Let Fiori elements prefill via inboundParameters

Keep your cross-app navigation as is – you already pass:


Navigation.navigate({
  target: { semanticObject: "zmrbsschedulecreate", action: "create" },
  params: {
    RoomId: roomId,
    DateScheduled: dateSche
  }
});

Make sure the app is launched in create mode

The Form Entry template usually already puts this in Component.js:

getStartupParameters: function() {
  return {
    preferredMode: ["create"]   // important for direct create
  };
}

Configure inboundParameters with useForCreate in the target app’s manifest.json

In your Book Room (Form Entry Object Page) app, add this under the object page target:

{
  "sap.ui5": {
    "routing": {
      "targets": {
        "BookRoom": {
          "type": "Component",
          "id": "BookRoom",
          "name": "sap.fe.templates.ObjectPage",
          "options": {
            "settings": {
              "contextPath": "/Schedule",          // your entity set
              "inboundParameters": {
                "RoomId": {
                  "useForCreate": true
                },
                "DateScheduled": {
                  "useForCreate": true
                }
              }
            }
          }
        }
      }
    }
  }
}

Important: The keys inside inboundParameters (RoomId, DateScheduled) must exactly match the OData property names of your Schedule entity, and the names of the startup parameters you pass via navigation (which you already do).

When this is in place and you navigate with preferredMode=create + startup parameters:
- Fiori elements will create a new instance of Schedule
- It will copy RoomId and DateScheduled from the startup parameters into the new context
- The Form Entry Object Page fields will be prefilled automatically (no controller extension needed)

Option 2: Prefill in a controller extension – but use routing.onAfterBinding

sap.ui.define(["sap/ui/core/mvc/ControllerExtension"], function (ControllerExtension) {
    "use strict";

    return ControllerExtension.extend("zmrbsschedulecreate.ext.controller.CreateScheduleController", {
        override: {
            routing: {
                // Called after the page is bound and the create context exists
                onAfterBinding: function (oContextInfo) {
                    // Get startup parameters
                    const oComponent = this.base.getAppComponent();
                    const oParams = oComponent.getComponentData()?.startupParameters || {};

                    // Get the page binding context (create context)
                    const oContext = this.base.getExtensionAPI().getBindingContext()
                        || oContextInfo?.bindingContext; // depending on UI5 version

                    if (!oContext) {
                        console.warn("No binding context available in onAfterBinding.");
                        return;
                    }

                    // Startup parameters are arrays: ["value"]
                    const sRoomId       = oParams.RoomId && oParams.RoomId[0];
                    const sDateScheduled = oParams.DateScheduled && oParams.DateScheduled[0];

                    if (sRoomId) {
                        oContext.setProperty("RoomId", sRoomId);
                    }

                    if (sDateScheduled) {
                        // Adjust parsing as needed, e.g. if you pass yyyy-MM-dd
                        // const oDate = new Date(sDateScheduled);
                        oContext.setProperty("DateScheduled", sDateScheduled);
                    }
                }
            }
        }
    });
});
Sign up to request clarification or add additional context in comments.

1 Comment

I used option 2 and it worked. Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.