I'm looking for help with setting a default tab in a Freedom UI page.

I want the "Lead Info" tab (which is the first tab) to always be selected by default when opening a lead record. However, after I perform or complete an activity and return to the Lead page, it automatically opens the "Lead Activities" tab instead of the "Lead Info" tab.

Is there a way to set the page to always open the "Lead Info" tab, regardless of the last active tab or navigation history?

Like 0

Like

2 comments

You can set the active tab using something like this (where "Tabs" is the name of the tab control): 

request.$context.Tabs_SelectedTabIndex_Profile = 0;

I've not tried setting that in the crt.HandleViewModelInitRequest, but it could work - although might need to wrap in a setTimeout just to break out of the message loop and let the page load first and for the saved user profile for selected tab is loaded first (I don't believe there is a way to prevent that). Try something like this:

{
    request: "crt.HandleViewModelInitRequest",
    handler: async (request, next) => {
        setTimeout(() => { request.$context.Tabs_SelectedTabIndex_Profile = 0; }, 1000);
        return await next?.handle(request);
    }
}

Might need to play with the timeout interval (the 1000), although it's not 100% it will work.

Ryan

Try using this code in the  handler:

      {

      request: "crt.HandleViewModelInitRequest",

      handler: async (request, next) =>{

        request.$context.Tabs_SelectedTabIndex_Profile=0;

        return next?.handle(request);

      }

    }

Show all comments

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

Hello,

Could I get some help understanding or directing me to an article that thoroughly explains the lookup titled "Package in installed application?"

What does the "Primary" check box do? What does the "Current package" check box do?

Can a package be named in more than one row, aka, more than one application?

I cannot locate an academy article explaining this function.

Like 0

Like

1 comments

Check out this article:

Store app data | Creatio Academy

Show all comments

How can i add new page parameter in pre-configured page in default creatio pre-configured page in freedom ui

Like 1

Like

2 comments

In the page designer, expand page parameters and add them there

Ryan

Hi Ryan Farley,

i just want to display the existing data source and the parameter, can i add to the parameter on the pre-configured page with the existing default parameter?

because in here i have most of the parameter but,

on the pre-configured page i just have some of them

Show all comments

I have two attachment pages, but when I attach a file on the first page, it also appears on the second page. How can I implement a filter so that the attachment only shows on the page where it was uploaded? i'm using FreedomUI.

 

Like 0

Like

2 comments
Best reply

You can use tags. The File objects have a Tag field, you can set up each file list to have a different tag, then the tag will get added to the file based on which list the file was added to, and the lists will also filter by this tag.

To do this, you simply need to enter a tag name for each of the file lists, just type in a value in the File tag property: 

Ryan

You can use tags. The File objects have a Tag field, you can set up each file list to have a different tag, then the tag will get added to the file based on which list the file was added to, and the lists will also filter by this tag.

To do this, you simply need to enter a tag name for each of the file lists, just type in a value in the File tag property: 

Ryan

Ryan Farley,

Thank you Ryan

Show all comments

After adding records ,How can I reload a detail list in a Freedom UI page from a task script within a business process, without using the live update feature in the object?
Thank you

Like 0

Like

3 comments

Note that i'add this code in the task script in the process 


var userConnection = Get<UserConnection>("UserConnection");
string messageText = "Successful";

Terrasoft.Configuration.MsgChannelUtilities.PostMessageToAll("ReloadDetail", messageText);
return true;    

i got this error message 
"The type or namespace name 'MsgChannelUtilities' does not exist in the namespace 'Terrasoft.Configuration' (are you missing an assembly reference?"

 

 

"The type or namespace name 'MsgChannelUtilities' does not exist in the namespace 'Terrasoft.Configuration' (are you missing an assembly reference?" - this error message will occur in case the business process is created in the assembly package. The only workaround is to uncheck the "Assembly package" property in the package settings or move the process to the regular package.

 

As for the possibilities and if LiveUpdate is not an option - yes, socket nessage to the client-side and triggering the LoadDataRequest with reload enabled is the only option.

I also encountered this same error, but in my case, it was due to a dependency issue. I resolved it by adding the 'crtBase' package as a dependency in the package containing the business process.

Show all comments

Hi Community,

I want to run a function only if the SaveRecordRequest is true. I tried to run await next.handle(request), but it returns undefined even if the record is save is successfully. Here is my code and test result:

 

 

			{
				request: "crt.SaveRecordRequest",
				handler: async (request, next) => {
					const saveResult = await next.handle(request);
					if(saveResult) {
						const id = await request.$context.Id;
						const files = await request.$context.SPJFile;
						await carPooling.uploadSPJ(id, files);
						request.$context.SPJFile = null;
					}
 
					return saveResult;
				}
			},
Like 0

Like

1 comments
Show all comments

Hello Community, 

We have a button in Freedom UI that calls a Business Process.

We want this button to be disabled at least for several seconds, till the process is completed. Clicking the button again, while the BP is still running might bring several issues to our logic.

(Printscreen: Button calling BP)

How can this be achieved?

Regards,Sasor

Like 1

Like

4 comments

Interesting idea :)

We could do with this.  I think I may have implemented this in the past by disabling the button on calling the process, and using the Send Message element at the end of the business process to publish a message that the client module is subscribed to to re-enable the button.

Hello community,

Is there any other way besides the Backend-Frontend websocket (which I havent tried yet)?

Sasori

Sasori Oshigaki,

As long as the process is not set to run in background, and you're starting the process via code, you can use the method outlined in the article below to know that the process has completed and re-enable the button without the need for messages: https://customerfx.com/article/starting-a-process-from-client-side-code-on-a-creatio-freedom-ui-page-and-getting-back-outgoing-process-parameters/

Ryan

Show all comments

Dear,

We are currently moving from classicUI to freedomUI and I m not able to do a simple filter on a lookup.

I want to filter a contact lookup of the account page. I only want to display the account contacts.

So in the account page business rules i did :

But the lookup is not filter

What do i miss ?

Is it because there is no condition ?

Thank you in advance,

Nicolas

 

Like 0

Like

4 comments
Best reply

Yes, you have to populate the condition part. You can create an always true condition as a workaround (true == true).

Yes, you have to populate the condition part. You can create an always true condition as a workaround (true == true).

Fyi this is fixed in 8.2.2. Release notes mention: Streamlined business rule setup. "Dynamic filter" and "Set value" business rules no longer need conditions to work

i had to add a condition then the rules works. i added if id is filled in.

I managed to filter a contact lookup using a business rule based on the contact's account name. For another contact lookup, I need to filter the contact ID to match the page's account ID.
can this filter be implemented as a business rule ?
after several days of research, I still don't see how to perform this filter without code...
Can someone help me please ?

Show all comments

Hi, 

Does Creatio support multi-select downdrop lists?

Like 0

Like

1 comments