Hi Community,

I'm working with Creatio Freedom UI and I need to embed a custom HTML layout along with some JavaScript logic (e.g., loading an external widget) into a page.

I’m looking for a proper way to add both:

  • Custom HTML code,

    .......

    </head>
    <body>
        <div style="width: 100%;">
            <div id="xyz1"></div>
            <div id="xyz2">
                <div style="width: 100%;">
                    <div id="queryBox" style="width: 100%;"></div>
                </div>
            <div  id="xyz3"></div>
            </div>
        </div>
    </body>
    </html>

  • External or inline JavaScript code (e.g., via <script> tags)

I've tried using custom components and inserting HTML using JavaScript (e.g., innerHTML), but I'm unsure if this is the recommended approach or if there's a native method provided by Creatio.

Could someone please guide me on:

  • The best practice for injecting HTML/JS into Freedom UI pages
  • Whether I can safely reference external JS/CSS (like from a CDN)
  • Any Creatio-supported way to dynamically render and control such elements

Thanks in advance! 
Any documentation links or working examples would be really helpful.

Regards,

Ajay Kuthe

Like 3

Like

1 comments
Best reply

Creatio does allow you to create your own custom UI components that you can add to the UI and even handle requests, read data, bind properties, etc. Documentation here on creating custom components: https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/category/freedom-ui-component

Video tutorial here: https://www.youtube.com/watch?v=CE5uETqTsyQ&list=PLnolcTT5TeE2BMFf_XmJrSwpnbcLCLJkb

A simple approach (with limited capabilities compared to creating a full control) can be seen here: https://customerfx.com/article/embedding-an-iframe-on-a-creatio-freedom-ui-page/ (you could use this approach to render any HTML, not just an IFRAME as the article shows)

Ryan

Creatio does allow you to create your own custom UI components that you can add to the UI and even handle requests, read data, bind properties, etc. Documentation here on creating custom components: https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/category/freedom-ui-component

Video tutorial here: https://www.youtube.com/watch?v=CE5uETqTsyQ&list=PLnolcTT5TeE2BMFf_XmJrSwpnbcLCLJkb

A simple approach (with limited capabilities compared to creating a full control) can be seen here: https://customerfx.com/article/embedding-an-iframe-on-a-creatio-freedom-ui-page/ (you could use this approach to render any HTML, not just an IFRAME as the article shows)

Ryan

Show all comments

Hi Creatio Community,

I'm currently working with an editable detail grid, and I need to filter a lookup column (UsrPort) based on the connected user's roles ("Stay SPOC TC", "Stay SPOC Casablanca", "Stay SPOC Jorf Lasfar", "Stay SPOC Laayoune", and "Stay SPOC Safi").

I've tried several approaches including:

  • Defining lookupListConfig with prepareList binding (works fine on regular pages but does not trigger in editable grids).



    Here's the latest implementation I've tested:
     

generateActiveRowControlsConfig: function(id, columnsConfig, rowConfig) {
    this.mixins.ConfigurationGridUtilitiesV2.generateActiveRowControlsConfig.call(this, id, columnsConfig, rowConfig);
 
    var scope = this;
 
    Terrasoft.each(rowConfig, function(columnItem) {
        var columnKey = columnItem.key && columnItem.key[0];
        if (columnKey && columnKey.name === "UsrPort") {
            columnItem.controlConfig = columnItem.controlConfig || {};
            columnItem.controlConfig.lookupListConfig = columnItem.controlConfig.lookupListConfig || {};
            columnItem.controlConfig.lookupListConfig.filter = function() {
                var filters = Terrasoft.createFilterGroup();
 
                // Example of role checks
                var allowedPorts = [];
                if (scope.get("IsStaySpocCasa")) allowedPorts.push("CASABLANCA");
                if (scope.get("IsStaySpocJorf")) allowedPorts.push("JORF LASFAR");
                // Add similar checks for other roles
 
                if (allowedPorts.length > 0) {
                    filters.add("PortFilter", Terrasoft.createColumnInFilterWithParameters("Name", allowedPorts));
                } else {
                    filters.add("EmptyFilter", Terrasoft.createColumnFilterWithParameter(
                        Terrasoft.ComparisonType.EQUAL, "Id", Terrasoft.GUID_EMPTY));
                }
 
                return filters;
            };
        }
    }, this);
},

This configuration currently doesn't work and results in the error mentioned above.

Could someone help clarify the correct way to implement role-based filtering on lookup columns within editable detail grids? If anyone has successfully implemented this or faced a similar issue, your guidance would be greatly appreciated!

Thanks in advance for your help!

Best regards,

Like 0

Like

2 comments

For classic details, rules implemented on the page are also manifested in the list for the detail. I believe you can just implement the filtering for the lookup on the page for the detail, then it will work in the list as well. 

Thank you Ryan  for your answer!
Actually, my detail is an editable grid. I noticed that the page-level lookup filtering doesn't propagate into editable grids automatically. From my tests and observations, the editable grids seem to require explicit filtering logic within the generateActiveRowControlsConfig method instead.
Could you please confirm if this understanding is correct, and perhaps suggest any best practices or examples explicitly for editable grids?

Show all comments

I am trying to create a folder in the Contacts Freedom UI List Page that only contains Contact records that are currently active. I know there is a field in the System Administration Object that is an Active status field (shown in the Users list page). I am trying to access this field; however, it is not showing up in the dropdown list of columns in the filter builder popup page. Any help would be great. I attached an image showing the columns currently visible to me for that System Admin Object. 

Like 0

Like

2 comments
Best reply

It would look like this - I typically also add Type=4 for users (although that’s a little redundant) and also add Connection Type=0 to get employee users (not external/portal users). 

Basically, from your screenshot, click "Quantity". Then set count > 0 (or click count to change to exists), then add the sub-conditions under that.

Ryan

It would look like this - I typically also add Type=4 for users (although that’s a little redundant) and also add Connection Type=0 to get employee users (not external/portal users). 

Basically, from your screenshot, click "Quantity". Then set count > 0 (or click count to change to exists), then add the sub-conditions under that.

Ryan

Ryan Farley,

Thank you Ryan for your time and help! This solution worked for me. 

Show all comments

I need to create a mask for this text field, it is a document, which has 11 digits, and is written as follows: ###.###.###-##.

I also want to limit the quantity and leave only periods and hyphens for typing.

The quantity entered is 11, but with the mask it becomes 14, I don't know if it is possible to block this.

Can anyone help me with this?

{
	"operation": "insert",
	"name": "Input_CPF",
	"values": {
		"type": "crt.Input",
		"multiline": false,
		"label": "$Resources.Strings.PDS_SCCPF_luo5kno",
		"labelPosition": "auto",
		"control": "$PDS_SCCPF_luo5kno"
	},
	"parentName": "FlexContainer_6gej1t9",
	"propertyName": "items",
	"index": 1
}
Like 0

Like

2 comments
Best reply

Hello,

 

In order to create the mask for the text field you can add a handler that will apply formatting to the text field value when user are typing.

 

You can use the following code snippet as an example:

 

{
	request: "crt.HandleViewModelAttributeChangeRequest",
	handler: async (request, next) =&gt; {
		if(request.attributeName == "PDS_SCCPF_luo5kno"){
			let value = await request.$context.PDS_SCCPF_luo5kno; 
			value = value.replace(/\D/g, ""); // Remove non-digit characters
			if (value.length &gt; 11){
				value = value.slice(0, 11); // Limit to 11 digits
			}
			let formatted = "";
			if (value.length &gt; 0) {
				formatted += value.slice(0, 3);
			}
			if (value.length &gt;= 4) {
				formatted += "." + value.slice(3, 6);
			}
			if (value.length &gt;= 7) {
				formatted += "." + value.slice(6, 9);
			}
			if (value.length &gt;= 10) {
				formatted += "-" + value.slice(9, 11);
			}
			request.$context.PDS_SCCPF_luo5kno = formatted;
 			request.preventAttributeChangeRequest = true;
		}
		return next?.handle(request);
	}
}

Hello,

 

In order to create the mask for the text field you can add a handler that will apply formatting to the text field value when user are typing.

 

You can use the following code snippet as an example:

 

{
	request: "crt.HandleViewModelAttributeChangeRequest",
	handler: async (request, next) =&gt; {
		if(request.attributeName == "PDS_SCCPF_luo5kno"){
			let value = await request.$context.PDS_SCCPF_luo5kno; 
			value = value.replace(/\D/g, ""); // Remove non-digit characters
			if (value.length &gt; 11){
				value = value.slice(0, 11); // Limit to 11 digits
			}
			let formatted = "";
			if (value.length &gt; 0) {
				formatted += value.slice(0, 3);
			}
			if (value.length &gt;= 4) {
				formatted += "." + value.slice(3, 6);
			}
			if (value.length &gt;= 7) {
				formatted += "." + value.slice(6, 9);
			}
			if (value.length &gt;= 10) {
				formatted += "-" + value.slice(9, 11);
			}
			request.$context.PDS_SCCPF_luo5kno = formatted;
 			request.preventAttributeChangeRequest = true;
		}
		return next?.handle(request);
	}
}

Thanks so much.
It worked wonderfully.

Show all comments

Dear,
I made a forecast on the products ordered by customers in order to obtain the total quantities per product ordered over several years and by year.
Now I would like to display this data on the account page as a table filtered by account.
Is it possible to access the forecast tables and display filtered data (by account) ?

Thank you,
Nicolas

Like 0

Like

1 comments

Dear Nicolas,

You can implement this logic in Freedom UI pages using "Apply filter by page data". 


Below, you can see an example of this binding using "Case Lifecycle" list as an example:

image.png

Here is a link on how to set this up: https://academy.creatio.com/docs/8.x/no-code-customization/customization-tools/ui-and-business-logic-customization/element-setup-examples/components/set-up-list-components#title-2761-2 

I hope this helps. Have a great day!

Show all comments

Hi.
Newbie here, so bear with me.  Best I start with an example --  

  • We have 200+ users who are sales reps and 2 Admins.
  • Some of these sales reps are managers of a sub-set of other subordinate reps.
  • Now, a rep quits, and it's up to an admin (in another country BTW) to manually go in and reassign his dozens of opportunities to a new sales rep.  This is a task his manager should be able to do, but can't (because only an admin can change other users' records).

This is just one example of a typical issue we run into, that could be fixed by giving "modify" rights to one user over certain other user's records -- or a "superuser" as exists in our other systems.

In Creatio, I am told only the individual rep can change his own "opportunities".  His manager cannot.  (The Admins of course can change everything about everyone, so logically we can not give admin rights to the managers.)

Is there a way around this?  
Perhaps the next release of Creatio will have some sort of granularity of "rights"? 

Thanks!
Rob

 

Like 0

Like

4 comments
Best reply

Creatio does have this, or at least it can work like this. If you're using organizational roles, each organizational role can have a management role. The management role inherits the permissions of the users in the organizational role. Meaning, if you create an org role called "sales" and then add an management role for the sales org role, the people in the management role inherit the permissions of the users in the org role. See https://academy.creatio.com/docs/8.x/setup-and-administration/administration/user-and-access-management/user-management/organizational-roles#title-2266-2

Note, this often means you also need to setup object/record permissions for things based on these roles as well, instead of by users (so the permissions can be inherited by the managers of the role). For example, you could add record access permissions that if anyone in "sales" creates a record, that edit permissions is given to anyone in the "sales managers role".

Ryan

Creatio does have this, or at least it can work like this. If you're using organizational roles, each organizational role can have a management role. The management role inherits the permissions of the users in the organizational role. Meaning, if you create an org role called "sales" and then add an management role for the sales org role, the people in the management role inherit the permissions of the users in the org role. See https://academy.creatio.com/docs/8.x/setup-and-administration/administration/user-and-access-management/user-management/organizational-roles#title-2266-2

Note, this often means you also need to setup object/record permissions for things based on these roles as well, instead of by users (so the permissions can be inherited by the managers of the role). For example, you could add record access permissions that if anyone in "sales" creates a record, that edit permissions is given to anyone in the "sales managers role".

Ryan

Ok, Thanks -- that's kind of what I thought, with my rudimentary experience with roles (and Creatio in general).

So, applying this to our large sales organization ...
Instead of implementing a single "sales" role, we would need to implement a "superuser" role, but for each sales division -- perhaps?

For example, we have 8 sales regions, like "Asia" and "Europe" and "South America".  There are 30-50 sales reps in each region.
We don't want all their "issues" trickling up to one admin, so as I mentioned we want a "SuperUser" in each region:  "SuperUser-Asia", SuperUser-India" and so on.  I guess these would be "management" roles in Creatio.

So, we would have to divide up the Sales Reps (users) into separate orgs (one for each region) so that their data would be visible to their SuperUser? 
Can I create separate orgs in Creatio, all living underneath the main Company org?

Thanks -- any suggestions you have are appreciated!

Rob

Yes, the roles are hierarchical. Each sub role inheriting the permissions of the roles before. You can have a role for sales, then sub roles for each division. Each division can have a managers role which could give them inherited permissions for the division they manage.  

I will have to review this with our integrator.   They are telling us that in the forthcoming release of Creatio, there are some enhancements to roles and permissions -- Are there any hints or documentation as to what this might be?   We need to allow certain roles to be able to edit specific data but not all.

(For example, a salesman creates a customer account DuPont Paints and can assign it to a "master" account DuPont International. This is really something that his local manager admin should also able to do, but can't)

Show all comments

Hello, 

We are trying to Implement a custom campaing element, SMS. 
We are following instructions from this website  : https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/8.1/platform-customization/classic-ui/marketing-campaigns-basics/examples/implement-a-campaign-element#title-1455-3
We are facing a issue.
We created a test package named FZCreateCampaignElement which depends on our package FZCustomer360. Other package FZCustomer360 depends on : CrtBaseFinserv,
CrtBulkEmailInC360 ,CrtCampaignElements ,CrtCampaignInC360,CrtCampaignUtils,CrtContactToLeadInC360,CrtCustomer360App,CrtDigitalAdsInC360,CrtEngagementInC360,CrtEventInC360,CrtFinservSalesAndServiceApp,CrtLeadOppMgmtInC360,CrtOpportunityInC360,CrtSLAInC360,MarketingCampaign

Successfully we did this steps : 

1. Create a marketing campaign element
2. Create a property panel for the campaign element
3. Add the element to the element area of the Campaign Designer

At step 4 when (4. Create an executable element for the campaign element ) we created   executable element, we could not publish it since the class CampaignFlowElement could not be inherited.


Like 0

Like

2 comments

Hello,

Please reattach your screenshot since its corrupted and cannot be reviewed. In general please make sure your package where the element is developed is not the assembly package and that the product that you are working in is of marketing build (like sales-enterprise-marketing-service-enterprise).

Hi Enjio! How are you? As a quick workaround, you could use "Add Data," element add a record, for example, in a "LogSMS" custom entity, and create a BP that has a trigger on that table and the logic for sending the SMS.

Show all comments

Hello;
In my 7.17 version i create a file repository override class and it work correctly
when I try to upgrade to 8,2,1 the FileService core class change and it create fileRepository object based on interface not class (ClassFactory.Get) and it run based method loadFile not override one.
Is it any solution to set the the default class for interface

Like 0

Like

2 comments

Hi,

Yes, starting from version 8.x, Creatio uses dependency injection (DI) more actively, including for services like IFileRepository, which is now resolved via ClassFactory.Get&lt;IFileRepository&gt;().

To override the default implementation, you can register your custom class as the default for the interface in the dependency container.
 

Solution: Register your class for the interface

You have to create your own AppEventListener and bind your class to the appropriate interface there.

 

public class UsrAppEventListener : AppEventListenerBase
{
	public override void OnAppStart(AppEventContext context) 	{
		base.OnAppStart(context);
		ClassFactory.Bind&lt;IFileRepository, CustomFileRepository&gt;(reuseType: ReuseType.Singleton);
    }
}

 

Where:

  • CustomFileRepository is your custom class that implements IFileRepository
  • ReuseType.Singleton (or None) depends on your usage

⚠️ Important: Ensure your class fully implements the IFileRepository interface.

This way, when FileService calls ClassFactory.Get&lt;IFileRepository&gt;(), it will receive your custom implementation.

TU Irina

Show all comments

How do I know what the current app package is?

Thanks,

Like 0

Like

2 comments

The new behavior is Creatio tries to make it's best judgement of where to save things, it does NOT use the Current Package setting. It's not often correct in where it decides to save things IMO and a bit frustrating, so there's really no where to see it because the system will decide differently based on what item you're trying to save. This article shows how to force save a page into a certain application's pacakge or to turn off the new way and revert back to using the Current Package system setting instead: https://customerfx.com/article/reverting-the-behavior-for-saving-pages-in-the-creatio-freedom-ui-designer-to-use-current-package-setting/

Ryan

Thanks Ryan,

we are trying to have App/package structure where one App has all of the objects and then all of the different apps are dependent on the Data from the DB package.

Intention is to deliver independently from data model different apps for different projects ongoing in the customer

This would work fine with classic but now we are running into some question because of this "smart" behavior.

Last example was Creatio added a field in the activity object to link to custom object when we added a list to the page of the custom object

Do you think this approach would fix these issues?

 

Thanks again

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