Original Reference: Ryan Farley, “Getting Multi‑select Records from a Creatio Freedom UI List via Code” Customer FX, Jan 30, 2024 

 

The Challenge

In Creatio 8.1+, lists support multi‑selection. Ryan’s post shows how to bind a custom bulk‑action button and read the DataTable_SelectionState attribute:

const selectedIds = (await request.$context.DataTable_SelectionState).selected;

However, this only covers the case where users manually pick some rows (“specific” selection). If they click “Select All,” the selected array is empty and selectionState.type === "all", with an unselected array instead. Nor does the basic snippet iterate through all pages of data.

An Alternative, Complete Handler

The code below demonstrates how to:

  1. Detect whether the user chose a subset (“specific”) or all records (“all”).
  2. Extract the true list of record IDs in both cases.
  3. Execute a business process for each record.
  4. Access other context values (e.g. an Opportunity ID wrapped in a  proxy).
{
 request: "cfx.ButtonClicked",
 handler: async (request, next) => {
   // 1. Retrieve selection state
   const selectionState = await request.$context.DataTable_SelectionState;
   // 2. Grab manual selections (if any)
   const selectedIds = selectionState?.selected || [];
   // 3. Retrieve another context value (example: Opportunity ID)
   const opportunityProxy = await request.$context.UsrEntity_66d2fb2DS_UsrOpportunityId_dppjv0g;
   const opportunityId = opportunityProxy?.value;
   // Helper: execute business process
   const runBP = async (recordId) => {
     return request.$context.executeRequest({
       type: "crt.RunBusinessProcessRequest",
       processName: "UsrProcess_4e23e14",
       processParameters: {
         ProcessSchemaParameter1: recordId,
         opportunityId
       },
       $context: request.$context
     });
   };
   // 4. Handle specific selections
   if (selectionState.type === "specific") {
     if (!selectedIds.length || !opportunityId) {
       console.error("No records selected or missing Opportunity ID.");
       return;
     }
     for (const id of selectedIds) {
       await runBP(id);
     }
   // 5. Handle “select all”
   } else if (selectionState.type === "all") {
     // a. Get IDs the user explicitly un‑selected (if any)
     const unselected = selectionState.unselected || [];
     // b. Read the full page of items bound to the list
     const items = await request.$context.Items;
     if (!Array.isArray(items)) {
       console.error("Items binding is not an array.");
       return;
     }
     // c. Build a final list of IDs: include every item not in unselected
     const allIds = items
       .map(item => item.PDS_Id.__zone_symbol__value)
       .filter(id => !unselected.includes(id));
     if (!allIds.length || !opportunityId) {
       console.error("No records to process or missing Opportunity ID.");
       return;
     }
     for (const id of allIds) {
       await runBP(id);
     }
   }
   // 6. Continue the chain
   return next?.handle(request);
 }
}
How This Works
  • selectionState.selected vs. .unselected:
    • When users pick specific rows, selected holds their IDs.
    • When they click the header checkbox (“Select All”), the engine treats it as “all except any I un‑checked,” so selected is empty and type === "all". The unselected array lists exceptions.
  • Reading the full list (Items):
    • You only get the current page of records in the Items binding. If your grid is paginated, you’ll need to iterate through pages server‑side or adjust your viewModel to load all records you intend to process.

 

 

 

Like 1

Like

Share

1 comments

This is fantastic, thanks for sharing! 

For list's that are multi-select I believe there is also the following (with likely the same results, returns an array of Ids):

request.$context.MyList_SelectedRows

At least that was the case, haven't verified that is still present. 

Also, if the list isn't multi-select (meaning no checkboxes), then I don't believe SelectedRows or SelectionState has anything for the single selected row. For non-multi-select lists you'd get the selected row using (return's the row's Id): 

request.$context.MyList_ActiveRow

Ryan

Show all comments