Edit Subgrids Side by Side with Power Apps Grid or Editable Grid

There are a few blogs about opening the records of a subgrid in a dialog. For instance

While dialogs are a much better user experience than navigating away, I would like to write about another option we can use: side-by-side editing using Side Panes (here the learn sdk link). The difference between the Dialogs (opened with Xrm.Navigation.navigateTo) and Side Panes (using Xrm.App.SidePanes) is that dialogs are covering the form below, while the Side Panes allows us to use both screen sides in the same time.

For more details about Side Panes, here is my older blog about opening Custom Pages in Side Panes.

And here is how it feels like to open the subgrid records in a Side Pane.

https://www.youtube.com/embed/mCnVf_W81v4?version=3&rel=1&showsearch=0&showinfo=1&iv_load_policy=1&fs=1&hl=en&autohide=2&wmode=transparentOpen on YouTube
We can edit both the form on the left and right side.

To implement that, we use the same subgrid event as the other blogs (“OnRecordSelect”), and open the Side Pane for the selected record. Here we take care to use a unique id for the Side-Pane. That means that the SidePane window will be reused for each record from the subgrid.

Privacy Settings

Create a JavaScript WebResource (OppPosYearDemo.js in my case) with this content.

asyncfunctionDianamics_OpenTheRecordSidePane(executionContext){    const paneId = "diana_OppPosYearSidePane";    const formContext = executionContext.getFormContext();    const  entityName = formContext.data.entity.getEntityName();    const recordId = formContext.data.entity.getId();    if(recordId==null){        return;    }        const pane = Xrm.App.sidePanes.getPane(paneId) ?? awaitXrm.App.sidePanes.createPane({                   paneId: paneId,            canClose: true        });                    pane.width = 600;  //you can decide what's the width of the side pane.  //you could change the width for each record, in case you want to    pane.navigate({                pageType: "entityrecord",                entityName: entityName,                entityId : recordId        });      }

On the Form, customize a subgrid using “Power Apps grid control” (or “Editable Grid”), upload the JavaScript WebResource with the code above, and register the OnRecordSelect event.

Set Properties
Set Properties
Handler Properties
Don’t forget to “pass the execution context as first parameter”

That’s it. The Side-Panes opens on each click, but we can still use the ribbon (commands) for the subgrid and the form on the left side.

Side-Panes opens on each click

Keeping both forms in sync

Editing side-by-side using Side Panes means that same columns could be edited in both windows. The form is not able to access the Side Pane columns, but is able to refresh it. But from the Side Pane we have no sdk in order to refresh the form on the left side (and also no sdk to access the from). At least am I not aware of such sdk.

But a common programming technique in web is to use postMessage. Using postMessage we can send an event to the form on the left side, so we can refresh the subgrid if needed. This is not supported by the sdk, but it’s a web programming technique. I use it, and I don’t think it’s a bad practice, but of course you need to decide if you want to rely on it.

For that we need a script for the form opened in the SidePane (I’ve called it SendMessage.js). Since I need only to refresh the subgrid after I saved the form in the SidePane, I’m sending the postMessage on the OnPostSave event. There could be other use cases (like showing a sum for the subgrid on the right side), where you could want to attach also to other controls on the right side. But making the refresh to often, would lead to a bad user experience.

For the message I’m using, I’ve picked a unique messageName: “Dianamics.SidePaneChanged”. I’ll need to filter the messages on the form (left side) using this name. Here is the script for the form on the right side:

functionDianamics_RegisterSendMessage(executionContext){    functionsendMessageFromSidePane(executionContext){        const formContext = executionContext.getFormContext();        const entityName = formContext.data.entity.getEntityName();        const recordId = formContext.data.entity.getId();        Array.from(parent.frames).forEach((frame) => {            frame.postMessage({                messageName: "Dianamics.SidePaneChanged",                 data: {                    entityName: entityName,                    recordId: recordId                }            }, "*");        });           }        const formContext = executionContext.getFormContext();    formContext.data.entity.addOnPostSave(sendMessageFromSidePane);}

Load this JavaScript WebResource on the form opened on the Side Pane, and attach it to the OnLoad event (don’t forget to pass the execution context)

Form Properties

Now I need to receive the message on the form (left isde). For that I modify the first JavaScript WebResource (OppPosYearDemo.js), and add the function to receive the message, and check if I need to refresh the form, or a specific subgrid. I also check if the message is from the Side Pane and intended for this purpose (the messageName is “Dianamics.SidePaneChanged”).

functionDianamics_RegisterMessageListener(executionContext){    const formContext = executionContext.getFormContext();    window.addEventListener("message", (e) => {                  console.log("registered OnMessage", e);        if(e.data?.messageName === "Dianamics.SidePaneChanged") {                        const data = e.data.data;          console.log(data);          if(formContext.data.entity.getEntityName() == data.entityName && formContext.data.entity.getId() == data.recordId){              formContext.data.refresh(true);          }          else{            //to do: check if it's the subgrid entityName            formContext.ui.controls.get("Positions")?.refresh();          }         }      });        };

Here is the result:

The subgrid on the left form gets refreshed, when the form on the right side is saved
The subgrid on the left form gets refreshed, when the form on the right side is saved

The complete code can be found in by GitHub Repository

How far can we go?

Using this idea, we can include children from deeper relationships (up to 4 levels). So in extreme case, we have tables related like this

We’ve just implemented the use case where we go two levels deeper

We’ve just implemented the use case where we go two levels deeper

But if we consider that on both forms we can show subgrids with nested grids, we can reach the table 4 levels deeper

But if we consider that on both forms we can show subgrids with nested grids, we can reach the table 4 levels deeper

But if we consider that on both forms we can show subgrids with nested grids, we can reach the table 4 levels deeper

Right now the Power Apps Grid doesn’t allow us to register OnRowSelected events for the nested tables, but the “Editable Grid” does. Let’s hope the Power Apps Grid will support that soon too.

Going extreme now… don’t know if the user would like this experience though…

Set Properties
Registering the OnRowSelect for the nested tables using EditableGrid

For EditGrid nested records I needed to change the code a little (see in gitHub code, in the comment), because the entityName and id of the selected record works a little different, but it works.

Selected rows from nested grids to edit in the Side Pane
Selected rows from nested grids to edit in the Side Pane

What’s your favorite experience, to open subgrid records: using dialogs or using side panes?

About the Author

Dianamics PCF Lady | Microsoft MVP | Blogger | Power Platform Community Super User | 👩‍💻 Dynamics 365 & PowerPlatform Developer | ORBIS SE

Reference

Birkelbach, D., 2023, Edit Subgrids Side by Side with Power Apps Grid or Editable Grid, Dianabirkelbach.wordpress.com, Available at: https://dianabirkelbach.wordpress.com/2023/08/05/edit-subgrids-side-by-side-with-power-apps-grid-or-editable-grid/#more-4185 [Accessed on 11 September 2023]

STAY UP TO DATE

Catch up on the latest blogseBookswebinars, and how-to videos.
Not a member? Sign up today to unlock all content.
Subscribe to our YouTube channel for the latest community updates.

Share this on...

Rate this Post:

Share: