Persisting Case Fields from a Constellation DX Component (Widget)

We have a Constellation DX custom widget for Pega Platform 25.1.3. The widget loads an external JavaScript client that runs on each user’s machine. This client detects context changes and exposes them through a callback.

The widget runs in a case context, and the fields are present on the case. The callback is definitely firing.

My case has two properties, Institute and Tenant. I currently update the fields with

const institute = ctx.institute ?? ctx.compactString;
const actionsApi = pConn.getActionsApi();

actionsApi.updateFieldValue(".Institute", institute);
actionsApi.updateFieldValue(".Tenant", ctx.tenant);

This updates the client-side state/UI, but after reloading the case, the values are empty again. I understand that updateFieldValue() updates the Redux state and does not itself persist data to the server. I also tested setValue(), but with the same result.

Calling actionsApi.saveAssignment(pConn.getContextName()); can persist the value, but only when an assignment is open. This isn’t sufficient for my use case; the event may occur outside the context of an active assignment.

I’m looking for the supported Constellation/PCore/PConnect approach to:

  1. Update arbitrary existing case properties from a DX widget,
  2. Persist the changes back to the backend
  3. Do so when the event originates from an external JavaScript callback without an assignment being open (the case itself must be open, of course)

What’s the recommended approach for this scenario? Is a savable data page or backend action (e.g. case-wide action) required?

The details region is not a safe space for saving, and the redux store focus’ on the container app/primary_n/workarea_n, and when you are in the details region, it is picking from container app/primary_n. You can view this by calling PCore.getStore().getState() in your browser console.

A savable data page is likely preferable in these details read only region.

You could try and trigger in this sequence to ensure it is being set in the Redux Store and available for your saveAssignment.

actionsApi.updateFieldValue(“.Institute”, institute);
actionsApi.triggerFieldUpdate(“.Institute”, institute);
actionsApi.updateFieldValue(“.Tenant”, ctx.tenant);
actionsApi.triggerFieldUpdate(“.Tenant”, ctx.tenant);

The “correct” way to do this is through a case-wide action. Constellation very rightly puts constraints over what and how you can update to a case - essentially, you need an assignment that you have Perform access to, and that assignment has to specifically reference the fields you want to update. This way all changes can be tracked, audited against the user that made them, and we know that the changes being made are appropriate for the current point of the process flow. Allowing arbitrary updates to case data is very much against recommended best practice.

That said if you genuinely must allow this kind of update then, as Josh says, a savable data page will do it. Or create a custom REST endpoint to do the dirty work for you. But whatever you do, please do consider the data integrity of your case and the requirement to understand who has made what changes and when.

A case-wide action is recommended here:

await pConn.getActionsApi().openLocalAction('UpdateCaseFields', {

 type: 'Case'

});

Within that action, update the case properties (for example, Institute, Tenant, etc.). This approach ensures server-side validation, authorization, and persistence, even when no assignment is open.

In contrast, updateFieldValue() and setValue() only update the client-side Redux state and do not persist changes to the case.

While you could use a sequence such as:

await PCore.getCaseUtils().getCaseEditLock();

await updateCaseEditFieldsData();

the recommended approach for arbitrary case updates initiated from an external DX Component callback is to use a case-wide action.

This provides a more robust and supported pattern, with proper server-side processing and data integrity guarantees.

Thank you all for your replies. I agree, a case-wide action would be the best way forward. For now, I will likely terminate the user session, redirecting them to the login screen. This is because changing the institute end environment could also cause them to gain or lose access permissions.

I’ve found this method that does what I need, but it doesn’t seem to be documented:

pConn.getActionsApi().logout()

(Also see my other post, Terminating a User Session from a DX Component )