UIX v2: on selection change update dashboard error

Hi,

I am writing an application that should display information related to the selected object in a dashboard.

Part of information comes from calling a VEM.

I did same thing in the old UIX starting from the template that comes with visual studio template. All worked okay: just need to do in shellui.js:

myTab.ShowDashboard("my-dashboard", { ObjectVersion: objectVersion });
myTab.Visible = true;

an in dashboard.js needs to register Started event 

dashboard.Events.Register(MFiles.Event.Started, OnStarted);
function OnStarted() {}

In the new UIX if you do it in the same way it is working only when selecting the first object. For all next selection it doesn't work.

in main.js

async function ShowDashboard(tab, objectData, fileContent, shellFrame) {
  const dashboard = await tab.ShowDashboard("MyDashboard", {
    ObjectDetails: objectData,
    FileContent: fileContent,
  });

  console.log("Dashboard instance:", dashboard);
  await tab.SetVisible(true);
  await tab.Select();

  console.log("Dashboard updated successfully.");
  // shellFrame.ShowMessage("Dashboard updated successfully.");
}
in dashboard.js:
function OnNewDashboard(dashboard) {
  const customDataChangedEventHandle = dashboard.Events.Register(
    MFiles.Event.Started,
    () => {
         if (dashboard.CustomData?.FileContent) {
        creator.text = JSON.stringify(dashboard.CustomData?.FileContent);
        console.log("Updated with new data:", creator.text);
      } else {
        console.warn("No FileContent provided in CustomDataChanged.");
      }
    }
  );
}
Then, I tried to use UpdateCustomData from iDashboard. (the description of this method is: Refreshes React metadata card content. - is it working only with React? is it only refresh metadata card?)
So, my implementation according with the sample was this:
For main.js
async function ShowDashboard(tab, objectData, fileContent, shellFrame) {
  const dashboard = await tab.ShowDashboard("MyDashboard", {});

  console.log("Dashboard instance:", dashboard);

  await dashboard.UpdateCustomData({
    ObjectDetails: objectData,
    FileContent: fileContent,
  });

  await tab.SetVisible(true);
  await tab.Select();

  console.log("Dashboard updated successfully.");
  // shellFrame.ShowMessage("Dashboard updated successfully.");
}
For dashboard.js:
function OnNewDashboard(dashboard) {
    eventHandle = dashboard.Events.Register(
    MFiles.Event.CustomDataChanged,
    (data) => {
      console.log("Registered global event is: " + globalEventHandle);
      console.log("CustomDataChanged triggered with data:", data);

      if (data.FileContent) {
        creator.text = JSON.stringify(data.FileContent);
        console.log("Updated with new data:", creator.text);
      } else {
        console.warn("No FileContent provided in CustomDataChanged.");
      }
    }
  );
}
Sadly, I had the same behaviour. The dashboard was updated only for the first selected object. For all the next object selection, even if I sent new data, it was not updated.
Looking into console I found an error after the first selection:
mfapp-bundle-app.31e0bc503e92bf17f5c9.js:1 Uncaught TypeError: Cannot read properties of undefined (reading 'left')
at mfapp-bundle-app.31e0bc503e92bf17f5c9.js:1:1171224 
This means that I am doing something wrong in my call.
So, can anybody help to solve this? Has anybody experience in using this combination of selectionchanged show dashboard  in the new UIX? I have many examples in the UIX v1 but here there is something that I do not understand.
Thanks for help.
Viorel
  • Hi Viorel,

    I observed and reported to M-Files a similar behaviour for a listing dashboard (i.e. replacing the M-Files listing instead of showing in a tab). M-Files UIXv2 only ever calls our OnNewDashboard function once per user session and also only sends the Dashboard.Started event once per user session (in M-Files 24.10).

    For the second time we call ShowDashboard UIXv2 just surfaces the dashboard but sends no events to our code.

    Does your dashboard receive a Stop event? Mine does as soon as the dashboard is replaced with ShowDefaultContent or when user navigates to a different view. After the Stop event my dashboard remains hidden in the background but receives no UIX events, but UIX framework makes it visible on the next ShowDashBoard call. Very strange.

    I suggest you also report a bug so it gets priority to be fixed.

    I am also seeing the same uncaught TypeError, btw.

  • Thanks for sharing Martin. Seems like this could influence all in community that are developing new dashboards.

  • Hi!

    I've been able to reproduce your issue Viroel. It comes from the second ShowDashboard() call. Did you know that calling it a subsequent times is basically the same as calling UpdateCustomData()?  So always doing both, as you do, is redundant.  For now if you limit yourself to only calling ShowDashboard() the first time and only UpdateCustomData() after that it should work.  I do think this is a bug though, so will file a report for this and hope it gets fixed soon.

    For Martin, I think the behavior you are seeing is mostly expected. Your OnNewDashboard() function will only get called once as we do not tear down the dashboards and create new ones anymore.  You need to move to the UpdateCustomData approach as well, but unfortunately the shellFrame.ShowDashboard() method does not return the dashboard object for you to call UpdateCustomData() yourself with, nor does it seem to delegate to that method when you call it subsequent times.  This also seems to be a clear bug.  Did you get an issue number to track it with? If so, can you share it? Until a fix comes through, you could pass data to the dashboard through the generic NotifyApplication method and corresponding CrossApplicationNotification event with the same effect.  In fact I would recommend that approach always for dashboards to communicate back to the ShellUI (I know elsewhere we recommend using custom commands for that).

  • Yes, Craig submitted tracker item 171919 for the shellFrame.ShowDashboard() not returning a dashboard object.

    I understand that OnNewDashboard is only called once per session since you are reusing the page (good). However UIX is also sending a Stop event to the dashboard when I call ShowDefaultContent and no subsequent Started event the next time I call ShowDashboard. That is strange. Should we ignore Stop events then? So far I have used the Stop event to unregister event handlers and tear down certain objects so they can be garbage collected. In any case I need to rebuild the UI for each time the user navigates to a different view (corresponding to CustomData changing).

    Good idea with NotifyApplication  - I will look into it. I wasn't aware that NotifyApplication would send a CrossApplicationNotification event. So, do I understand you correctly: In my dashboard Start event handler (or in OnNewDashboard?) I should call ShellUI.NotifyApplication and pass the dashboard object back to the ShellUI. Then the ShellUI.CrossApplicationNotification handler should save that dashboard object reference to be used for subsequent calls to UpdateCustomData?

  • However UIX is also sending a Stop event to the dashboard when I call ShowDefaultContent and no subsequent Started event the next time I call ShowDashboard. That is strange. Should we ignore Stop events then?

    I do admit this seems a bit uneven, and there are probably some clear improvements we can make.  If the behavior is predictable though, even if not ideal, you should still be able to work with it.  Whether you want to tear things down on the stop event is up to you and your use case.  If you are going to re-render and re-register things when you get updated data and show the dashboard again, then maybe it makes sense.

    So, do I understand you correctly: In my dashboard Start event handler (or in OnNewDashboard?) I should call ShellUI.NotifyApplication and pass the dashboard object back to the ShellUI. Then the ShellUI.CrossApplicationNotification handler should save that dashboard object reference to be used for subsequent calls to UpdateCustomData?

    No, you are only allowed to pass serializable data/objects between different modules and dashboards, so you wouldn't be able to pass a dashboard reference.  You would simply call NotifyApplication() instead of the UpdateCustomData() on the module side and on the dashboard side you would listen for the CrossApplicationNotification event (using a custom type name for just this purpose) to receive the updated data instead of the CustomDataChanged event.

    This is how I showed modules and dashboards communicating at the partner conference back in May, before the CustomData method and event were added.

  • Hi Joel,

    You were right. I updated the code according with your suggestions (checking if dashboard was initialized before calling ShowDashboard and calling UpdateCustomData only if dashboard was initialized) and it is working.

    Thank you for help!

    Viorel