Hi Team,

 

To provide some context, I have three objects - A, B and C. Object C acts as a linking object between A and B

 

Currently, I have a page (object A) with detail (object C) on it. By clicking on "Add" button I open separate page (object C), that contains list (object B) with multiply selection. I need to filter out the records in list, that already exists in detail. After that I need to create records in object C using the selected records from list, along with the passed Id from the page (object A).

 

So, I have two questions:

1) How can I pass the Id from the page (object A) to page (object C), in order to filter out records in the list.

2) How can I filter out records (object B), that already exists in detail (object C).

 

I have successfully implemented it in Classic UI, but I'm unable to replicate it in Freedom UI due to the absence of a Sandbox

Like 0

Like

4 comments

Hello,



It could be achieved only with development tools.



Unfortunately, we don't have the exact examples of how to implement your business task, 

 

But you can try to check the article on how to filter a Lookup on a Creatio Freedom UI Page and change the code according to your needs:

https://customerfx.com/article/dynamically-filtering-a-lookup-on-a-crea…

You can also try to use Javascript's built-in Broadcast Channel API instead of the sandbox. See https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API

Ryan

Ryan Farley,

There is a way to use Broadcast Channel API  from freedom UI to Classic?

Found it: this works for me

subscribeSandboxEvents: function() {
					this.callParent(arguments);
 
					const bc = new BroadcastChannel("MyMessage");
                    bc.onmessage = async (event) => {
						debugger;
                        const MyObject = event.data;
 
                        bc.close();
                    };
				},

 

Show all comments

Hi Creatio Community,

We want to customize/extend functioanilty of the Account Form page found in Customer360 app.

Which is the right way to do it ?

Sasori

Like 0

Like

2 comments

Hi Community,

Any update regarding the topic?

Sasori

Greetings,



Firstly, please make sure that you are working in Freedom UI before applying any changes. You may apply the changes directly through UI or via customizing the package contents.

You may do so by following this Academy article:

https://academy.creatio.com/docs/user/platform_basics/freedomUI/turn_on_the_freedom_ui/general_procedure?_gl=1*h5poxo*_gcl_au*NDEwODkzNDYzLjE2ODk1OTEzNjc.



Second, you need to apply a few, certain changes to the app through the configuration. You may find more information on this subject here:



https://academy.creatio.com/docs/developer/development_tools/packages/packages_basics/overview

https://academy.creatio.com/docs/developer/architecture/composable_architecture/overview

https://academy.creatio.com/docs/developer/marketplace_app_development/app_compatibility/configure_the_app_for_composable_architecture_compatibility/overview



If you would like to export your packages for further customization on other applications, you can find more information on this subject using this guide:

https://academy.creatio.com/docs/developer/getting_started/transfer_application/overview



In regards to renaming packages.

Unfortunately, you can't rename the package once it is already exported, renaming the archive wouldn't change the package name itself. You can try to rename the package when it is still in the dev environment in the SQL console changing the name of the corresponding record in the SysPackage table. We don't recommend to do this, however, if it is really needed you can backup the database, change the name, generate the source code for all and compile all. After that, if while testing the functionality no errors would occur you can export the package and transfer it. 



 

Show all comments

In Freedom UI sections (ie Customer 360 Accounts and Contacts sections) I can't find the way to apply an advanced filter.

I see it's possible to create folders and set their filters but I don't find the same "Switch to advanced mode" action available in classic UI Creatio sections.

How can a user apply an advanced filter without the need of folders?

Thanks

Like 6

Like

4 comments

Did you find a method to apply advanced filters? I have the same problem here. 

Matthias Bendel,

 

At the moment there is not such functionality in the Freedom UI, but we already registered this idea for our R&D team and it may appear in future releases.

Hi! Is there any news regarding this feature?

 

Csilla Kiss,

Hello!

 

We are still working on this functionality, the R&D team has a task, so it should be available soon in new releases. 



Best regards,

Anton

 

Show all comments

Hi,

I've created a custom FreedomUI page for AccountAddress object. I'd like to implement some kind of automation for two lookup fields: Country and Region. It consists of two parts:

1. When I choose a region from list, the country should be set to region's country. For example, if I choose Texas region, I expect that country will be set to United States

2. When I choose a country, regions lookup should display only these regions, which are connected with selected country.

I haven't any problem with implementation of the first part. But the second part doesn't work I expected. I use handler for crt.LoadDataRequest to append a filter parameter when loading regions list. The problem is that this handler runs only once, at first list load. It doesn't execute when I change country, although I trigger such request from other handler (crt.HandleViewModelAttributeChangeRequest). Here is the crucial of my code:

{
	request: 'crt.LoadDataRequest',
	handler: async (request, next) => {
        if (request.dataSourceName === 'Region_List_DS') {
	        const predefinedFilter = await request.$context.Region_filter;
	        request.parameters.push({
		        type: "filter",
		        value: predefinedFilter
	        });
        }
 
		return await next?.handle(request);
	}
},
{
	request: 'crt.HandleViewModelAttributeChangeRequest',
	handler: async (request, next) => {
        if (request.attributeName === 'EvCountry' && request.value?.value != null && (request.oldValue?.value == null || request.value.value !== request.oldValue.value)) {
			const countryId = request.value?.value;
            request.$context.EvRegion_filter = {
				"items": {
					"1954b2e1-ea91-4014-b785-cda17020595c": {
						"items": {
							"CustomFilters": {
								"items": {
									"customFilterCountry_Region_1664cb4d-2690-48d6-bcdf-0c8075824efa": {
										"filterType": 1,
										"comparisonType": 3,
										"isEnabled": true,
										"trimDateTimeParameterToDate": false,
										"leftExpression": {
											"expressionType": 0,
											"columnPath": "Country"
										},
										"rightExpression": {
											"expressionType": 2,
											"parameter": {
												"dataValueType": 10,
												"value": countryId
											}
										}
									}
								},
								"logicalOperation": 0,
								"isEnabled": true,
								"filterType": 6
							}
						},
						"logicalOperation": 0,
						"isEnabled": true,
						"filterType": 6
					}
				},
				"logicalOperation": 0,
				"isEnabled": true,
				"filterType": 6
			};
 
			const handlerChain = sdk.HandlerChainService.instance;
			const result = await handlerChain.process({
				type: "crt.LoadDataRequest",
				$context: request.$context,
				config: {
					loadType: "load"
				},
				dataSourceName: "EvRegion_List_DS",
			});
		}
 
		return next?.handle(request);
	}
}

The problem is that my trigger (handlerChain.process call) doesn't run crt.LoadDataRequest, and result variable contains full, unfiltered list of regions.

Like 1

Like

5 comments

Hello,

 

Thank you for the code and description!

 

We've verified the issue and discussed it with our core R&D team: in 8.0.9 there will be a possibility to add filtration business rules using wizard capabilities in Freedom UI. Please wait until this version is released and use this rule type to create dynamic filtration in Freedom UI interface.

Oleg Drobina,

as filtration business rules do not cover all cases of filtration, when can we wait for trigger fix?

We have tested in 8.0.9 and have the same issue as described



Thank you!

Vladimir

Vladimir Sokolov,

 

indeed filtration rules (along with static filtering business rules) don't cover all cases, but most of them. As for the list loading and the LoadDataRequest - in 8.1.0 there will be new "filterAttributes" attribute added for each list of each data source with the boolean "loadOnChange" property that will allow dynamic setup of filters in the lists (including combobox). It will look like this:

"filterAttributes": [
					{
						"loadOnChange": true,
						"name": "AccountItems_FILTER_BY_ACTIVE_ROWS"
					}

where AccountItems_FILTER_BY_ACTIVE_ROWS will be the filter itself. So in 8.1.0 all filtration cases should be covered by this functionality.

Hello,

 

Glad to inform you that in 8.1.1 we've added the possibility to use custom filters in page schema handlers when working with SDK. So you can upgrade your apps and you will be able to use custom filtration on the page.

Hi Oleg,

 

Do you have the code / Procedure to do this in 8.1.1 ?

Show all comments

Hello,

 

Can any one help me how to get "Description" of a lookup type field and Populate it in any Other Field via code in freedomUI ? 

Like 0

Like

2 comments
Best reply

I'm positive there is a way to register the field as an attribute for the Lookup's data source, I've just not figured out or tested how to do that yet. Likely info here https://academy.creatio.com/docs/developer/front_end_development_freedo…

As for now, you could do the following - in this example I have a lookup for ContactType and will retrieve the Description once selected. You'll ned to know the actual attribute name for the lookup which you can see in the viewDiffConfig for the control as:

control: "$SomeAttributeName"  (this is the attribute name, minus the "$")

Then, add a change request handler like this: 

{
	request: "crt.HandleViewModelAttributeChangeRequest",
	handler: async (request, next) => {
		// listen for changes to the Lookup field attribute
		if (request.attributeName === "LookupAttribute_spr6dlv" && !request.silent) {
			// get the selected value
			var lookupVal = await request.$context.LookupAttribute_spr6dlv;
			// retrieve the description
			const model = await sdk.Model.create("ContactType");
			const results = await model.load({
				attributes: ["Description"],
				parameters: [{
					type: sdk.ModelParameterType.PrimaryColumnValue,
					value: lookupVal.value
				}]
			});
			const desc = results[0].Description;
			// set the other column's attribute with the description
			request.$context.SomeOtherAttribute = desc;
		}
 
		return next?.handle(request);
	}
}

Ryan

Hi,

 

Example of retrieving description value of the lookup:

const accountCategoryModel = await sdk.Model.create("AccountCategory");
					const accountCategory = await accountCategoryModel.load({
						attributes: ["Id", "Name", "Description"],
						parameters: [{
							type: sdk.ModelParameterType.PrimaryColumnValue,
							value: "38ea507c-55e6-df11-971b-001d60e938c6"
						}]
					});
					console.log("The result: ", accountCategory);

value: "38ea507c-55e6-df11-971b-001d60e938c6" - Id here can be dynamically set as some variable that is received from the context. To set the result for the column (in this case for the UsrSubjectDetails):

request: "crt.HandleViewModelAttributeChangeRequest",
    handler: async (request, next) => {
      if (request.attributeName === 'UsrSubject') {
        const isFieldsShouldBeSynchronized = request.oldValue === await request.$context.UsrSubjectDetails;
        if (isFieldsShouldBeSynchronized) {
          request.$context.UsrSubjectDetails = "some value";
        }
      }

 

I'm positive there is a way to register the field as an attribute for the Lookup's data source, I've just not figured out or tested how to do that yet. Likely info here https://academy.creatio.com/docs/developer/front_end_development_freedo…

As for now, you could do the following - in this example I have a lookup for ContactType and will retrieve the Description once selected. You'll ned to know the actual attribute name for the lookup which you can see in the viewDiffConfig for the control as:

control: "$SomeAttributeName"  (this is the attribute name, minus the "$")

Then, add a change request handler like this: 

{
	request: "crt.HandleViewModelAttributeChangeRequest",
	handler: async (request, next) => {
		// listen for changes to the Lookup field attribute
		if (request.attributeName === "LookupAttribute_spr6dlv" && !request.silent) {
			// get the selected value
			var lookupVal = await request.$context.LookupAttribute_spr6dlv;
			// retrieve the description
			const model = await sdk.Model.create("ContactType");
			const results = await model.load({
				attributes: ["Description"],
				parameters: [{
					type: sdk.ModelParameterType.PrimaryColumnValue,
					value: lookupVal.value
				}]
			});
			const desc = results[0].Description;
			// set the other column's attribute with the description
			request.$context.SomeOtherAttribute = desc;
		}
 
		return next?.handle(request);
	}
}

Ryan

Show all comments

Hello,

Lookup fields on Freedom UI have a feature that let user create a new record from lookup Field, like on the following screenshot (Owner field on Account Form Page):

I'd like to set some default values on such created record. For example, I'd like to set the new contact's account to current account record. I'm able to do this while using simple buttons, but I don't see such possibility for lookups.

It will be ok, even if the answer requires some coding, I have nothing against :)

 

Like 0

Like

4 comments

Hello,



You can set the default value for the column if the object settings:



 

Hi,

I know that its possible to set default value on the object level, but unfortunately it doesn't solve my problem. Let's see an example:



In Account, I have two important fields: Owner (which is my company employee, who takes care about the customer) and Primary contact (which is my customer, related with the account). Both fields refer to Contact records.

 

In Contact, I have a Type lookup, which I use to recognize whether a contact is my company employee or a customer.

 

I'd like to set Type to my company Employee, when adding record from Owner field, or set it to Customer otherwise. I can't do it by setting a default value on the object level.

 

Anyway, thank you for your answer :)

 

Hello again, do anyone know answer for my question? :)

Maybe try to set value through Business Rules. It can do this as much as I understood your query.

Show all comments

Hello,

some elements like button have "clicked" attribute, where we can configure which request should be emited and which params should be passed to its handler. I try to use this feature, but it doesn't always work I expected.

For example, I created two new elements on Accounts Form Page:

- a button

- a lookup (with adding new record from list control enabled)

 

The first one emit crt.CreateRecordRequest with some params, the second one consists of two viewConfigDiff entries: one of them is a crt.ComboboxSearchTextAction and emits crt.CreateRecordFromLookupRequest

request with no params.

I tried to add my custom param to both elements. You can see it at the source code I've attached to this post. Then, I created two handlers, for handling both types of requests. In the result I can access to my custom param from button click handler (the alert with text "Hello" shows up), but not for the lookup create new record handler (the alert display "undefined").

 

define("Accounts_FormPage", /**SCHEMA_DEPS*/[]/**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
	return {
		viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
			{
				"operation": "insert",
				"name": "ComboBox_xj333ko",
				"values": {
					"layoutConfig": {
						"column": 1,
						"row": 9,
						"colSpan": 1,
						"rowSpan": 1
					},
					"type": "crt.ComboBox",
					"label": "$Resources.Strings.LookupAttribute_it9tgfm",
					"labelPosition": "auto",
					"control": "$LookupAttribute_it9tgfm",
					"listActions": [],
					"showValueAsLink": true,
					"controlActions": []
				},
				"parentName": "SideAreaProfileContainer",
				"propertyName": "items",
				"index": 8
			},
			{
				"operation": "insert",
				"name": "addRecord_al7wl16",
				"values": {
					"code": "addRecord",
					"type": "crt.ComboboxSearchTextAction",
					"icon": "combobox-add-new",
					"caption": "#ResourceString(addRecord_al7wl16_caption)#",
					"clicked": {
						"request": "crt.CreateRecordFromLookupRequest",
						"params": {
							"MyParameter": "Hello" // HERE
						}
					}
				},
				"parentName": "ComboBox_xj333ko",
				"propertyName": "listActions",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "Button_93h456o",
				"values": {
					"layoutConfig": {
						"column": 1,
						"row": 10,
						"colSpan": 1,
						"rowSpan": 1
					},
					"type": "crt.Button",
					"caption": "#ResourceString(Button_93h456o_caption)#",
					"color": "default",
					"disabled": false,
					"size": "large",
					"iconPosition": "only-text",
					"visible": true,
					"clicked": {
						"request": "crt.CreateRecordRequest",
						"params": {
							"entityName": "Contact",
							"defaultValues": [
								{
									"attributeName": "Age",
									"value": null
								}
							],
							"MyParameter": "Hello" // HERE
						}
					},
					"clickMode": "default"
				},
				"parentName": "SideAreaProfileContainer",
				"propertyName": "items",
				"index": 9
			}
		]/**SCHEMA_VIEW_CONFIG_DIFF*/,
		viewModelConfig: /**SCHEMA_VIEW_MODEL_CONFIG*/{
			"attributes": {
				"LookupAttribute_it9tgfm": {
					"modelConfig": {
						"path": "PDS.EvColumn1"
					}
				}
			}
		}/**SCHEMA_VIEW_MODEL_CONFIG*/,
		modelConfig: /**SCHEMA_MODEL_CONFIG*/{}/**SCHEMA_MODEL_CONFIG*/,
		handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "crt.CreateRecordFromLookupRequest",
				handler: async (request, next) => {
					alert(request.MyParameter);
					return next?.handle(request);
				}
			},
			{
				request: "crt.CreateRecordRequest",
				handler: async (request, next) => {
					alert(request.MyParameter);
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,
		converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
		validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
	};
});

What can I do to make it's working? I use version 8.0.7 (.NET core).

---------------------

This alert displays after click on the button:

And this alert displays after trying to add new record from the lookup:

 

Like 0

Like

1 comments

Hello Eryk,

 

You did everything correctly according to the basic logic and I was able to reproduce the same behaviour on my end. Additionally I reviewed the request in debugger, its context and other properties and wasn't able to locate the "MyParameter". I will pass this info to our core R&D team so they could make it possible to operate with custom parameters in terms of the CreateRecordFromLookupRequest request handler.

Show all comments

Hello ,

I have a requirement where "A" is a date field and "B" is a boolean. When a record is created, it should calculate the number of days left until "A" arrives. If the number of days left is less than 45, then the value of "B" should be changed to "true". 

Note : I m using Freedom UI. Also if this is possible through Bussiness Process please Advise.

Like 0

Like

4 comments

Good day,

 

This can be done by making a formula to count days between "today" and your filed "A" with a function .Days.

It should look something like the following:

 

([#Date value.5/31/2023#]-[#System variable.Current Date#]).Days

 

I will also will leave some community questions on the matter:

https://community.creatio.com/questions/auto-calculate-age-based-new-bi…

https://community.creatio.com/questions/need-use-caluculated-field-valu…

 

Cheers.

Artem,



I have Created A process but data is not reflecting as i want.

Screenshot of Process and records are attached 

This is my SubProcess



This is my Main Process





This is the list of Records





Here Course C is the field which displays the Days which is not Correct. 

Please Advise



 

 

Hey there,

 

If you are referring to the way the data is represented, it depends on the type of the column (in order to make the value not have zero after it - make the column integer)

 

If you want to show a checkbox that would be ticked if a certain number is reached and you do not want to use code, keep the column in which you store the number of days, and on the base of it, build a business rule that "if the number of days is reached, then make the box true"



https://academy.creatio.com/docs/user/nocode_platform/freedom_business_…

 

Thank you

Artem,

 Thanks for your reply.

I want the value in Field should be correct as it is 92 for all records allthough there are some records whose value should be 30 days or 60 days

 

Show all comments

Hi Community,

 

I would like to know how we can make a column mandatory in an attachment list (the detail here) as soon as we upload a file to the detail.

 

 

Thanks in advance!

 

Regards,

Abilash.S

Like 0

Like

1 comments

To make a column mandatory in FreedomUI, you can follow these steps:

  1. Identify the column you want to make mandatory in the detail view of your form.

  2. Open the code or configuration file associated with your FreedomUI implementation.

  3. Locate the section or code block related to the detail view of your form.

  4. Find the column you want to make mandatory within the code or configuration.

  5. Depending on the specific implementation of FreedomUI, you can typically add a validation rule or attribute to the column to make it mandatory.

  6. Add the necessary code or configuration to enforce the mandatory requirement for the column. This may involve setting a "required" flag, adding a validation rule, or specifying a validation message.

  7. Save your changes and test the form to ensure that the column is now mandatory in the detail view.

It's important to note that the exact steps may vary depending on the version and customization of FreedomUI you are using. Refer to the documentation or consult with the developers or support team of FreedomUI for specific guidance on making a column mandatory in the detail view.



More detail : https://360degreecloud.com/

Show all comments

Hi Creatio Community,

 

I would like to know the name of the function/handler that's called when creating a record and saving it in an editable detail in FreedomUI so that we can override it. We also noticed SaveRecordRequest doesn't seem to be called here.

 

Thanks in advance.

 

Regards,

Abilash.S

Like 0

Like

4 comments

Hello,

 

These should be the crt.CreateRecordRequest request and the crt.CreateRecordHandler handler. Try those in either:

 

1) Page where detail is added

2) Detail schema

3) Edit page of the detail

 

and it should be triggered.

Oleg Drobina,

 

Tried these two methods. They don't seem to be called when creating and saving the records in an editable detail.

Abilash,



I tried this handler:

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "crt.CreateRecordRequest",
				handler: async (request, next) => {
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

on the schema where detail is added and it's successfully triggered:

It also depends on which handler you have specified in the "Add button" properties, you need to find it in the schema diff (in my case it was crt.CreateRecordRequest):

{
				"operation": "insert",
				"name": "GridDetailAddBtn_z5e8jja",
				"values": {
					"type": "crt.Button",
					"caption": "#ResourceString(GridDetailAddBtn_z5e8jja_caption)#",
					"icon": "add-button-icon",
					"iconPosition": "only-icon",
					"color": "default",
					"size": "medium",
					"clicked": {
						"request": "crt.CreateRecordRequest",
						"params": {
							"entityName": "Contact"
						}
					},
					"visible": true,
					"clickMode": "default"
				},
				"parentName": "FlexContainer_n5yrzkv",
				"propertyName": "items",
				"index": 0
			},

 

Oleg Drobina,

 

The detail we are working with uses an inline record to create new records which doesn't seem to be calling CreateRecordHandler or CreateRecordRequest. 











 

Show all comments