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.

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

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

async function Dianamics_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) ?? await Xrm.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.

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.

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:

function Dianamics_RegisterSendMessage(executionContext){

    function sendMessageFromSidePane(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)

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”).

function Dianamics_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 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

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…

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

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

One thought on “Edit Subgrids Side by Side with Power Apps Grid or Editable Grid

Add yours

  1. Hi Diana,
    thank you very much for this indepth guide!

    I was playing around with this and wondered, did you find a way to make this work with the Assosiated Grid Controll?

    Best regards,
    Claudio

Leave a comment

Website Powered by WordPress.com.

Up ↑