Hello. I need to create a QuickFilter on a Freedom UI Page whose value will change dynamically. I found a post https://customerfx.com/article/using-custom-attributes-on-a-creatio-fre… so I try to use the attribute but it does not work. Could you help me please?

{
    "filterType": 1,
    "comparisonType": 3,
    "isEnabled": true,
    "trimDateTimeParameterToDate": false,
    "leftExpression": {
        "expressionType": 0,
        "columnPath": "MyColumn"
    },
    "isAggregative": false,
    "dataValueType": 1,
    "rightExpression": {
        "expressionType": 2,
        "parameter": {
            "dataValueType": 1,
            "value": "$MyAttribute"
        }
    }
}
Like 0

Like

1 comments

Hello,
It seems that the attributes will not work properly with the filter, as an alternative I can suggest applying the full filter in a handler where you can change it as you want, for example:

		handlers: /**SCHEMA_HANDLERS*/[
          {
            request: "crt.HandleViewModelAttributeChangeRequest",
            handler: async (request, next) => {
            	const result = await next?.handle(request);
            	request.$context.DataGrid_7cyakqc_PredefinedFilter={"items": {
								"1893734f-7c93-40a5-9592-8e7231005e10": {
									"filterType": 1,
									"comparisonType": 7,
									"isEnabled": true,
									"trimDateTimeParameterToDate": false,
									"leftExpression": {
										"expressionType": 0,
										"columnPath": "Age"
									},
									"isAggregative": false,
									"dataValueType": 4,
									"rightExpression": {
										"expressionType": 2,
										"parameter": {
											"dataValueType": 4,
											"value": 20
										}
									}
								}
							},
							"logicalOperation": 0,
							"isEnabled": true,
							"filterType": 6,
							"rootSchemaName": "Contact"};
            	return result;
              }
          }
        ]
Show all comments
"PDS_UsrActualFuelRemaining_s06444m": {
                        "modelConfig": {
                            "path": "PDS.UsrActualFuelRemaining"
                        },
                        "validators": {
                            "MyNumberValidator": {
                                "type": "usr.MonthNumberValidator",
                                "params": {
                                    "minValue": "0",
                                    "message": "Допустимі значення від 0 до 500",
                                    "maxValue": "500"
                                }
                            }
                        }
                    },

 

If I specify a range, the validator works. But when I try to use <strong>var OldWorkHour = await request.$context.PDS_UsrWorkHours_sjx2srh;</strong>, I get an error.

Could you please help me figure out why this happens and how to fix it?

 

 "usr.MonthNumberValidator": {
   validator: function(config) {
       return function(control) {
           var controlValue = control.value !== undefined ? parseFloat(control.value) : null; 
 
           var minValue = config.minValue !== undefined ? parseFloat(config.minValue) : Number.MIN_SAFE_INTEGER; 
           var maxValue = config.maxValue !== undefined ? parseFloat(config.maxValue) : Number.MAX_SAFE_INTEGER; 
 
            var OldWorkHour = await request.$context.PDS_UsrWorkHours_sjx2srh;
 
           var isValueValid = controlValue >= minValue && controlValue <= maxValue;
           if (!isValueValid) {
 
               return {
                   "invalid": { 
                       message: config.message || "Введене значення не відповідає умовам"
                   }
               };
           }
 
           // Якщо все добре, повертаємо null (успішна валідація)
           return null;
       };
   },
   params: [
       {
           name: "minValue"
       },
       {
           name: "maxValue"
       },
       {
           name: "message"
       }
   ],
   async: false
},
Like 0

Like

2 comments

Hi,

 

And what is the datatype for the PDS_UsrWorkHours_sjx2srh and UsrActualFuelRemaining? And what is the error message you receive?

Hello,
The ability to add dynamic parameters to a validator is still under development, as a way around you can try using global variables like window. For example

handlers: /**SCHEMA_HANDLERS*/[
{
    request: "dw.StartDateChange",
    handler: async (request, next) => {
        window.StartDate = await request.$context.DateTimeAttribute_lpcf566;
        if(request.$context.IsStartDateInited) {
            request.$context.validate();
        }
        request.$context.IsStartDateInited = true;
        return next?.handle(request);
    }
}]                
...        

"dw.StartDateIsNotNotLessThanProjectStartDate": {
    "validator": function (config) {
        return function (control) {
            return (!control.value || control.value >= window.StartDate)
                ? null
                : {"dw.StartDateValidator": {message: config.message}};
        };
    },
    "params": [
        {
            "name": "message"
        }
    ],
    "async": false
}

Show all comments

Hello,

 

I need to call a code once a record gets created for the first time. This worked using the following:

handlers: /**SCHEMA_HANDLERS*/[
			{
        request: "crt.SaveRecordRequest",
        handler: async (request, next) => {

 

however what this does is execute the code for each attribute value change, which is not what is needed. How can I call this exactly once just when the record is created for the first time and that's it, without having to call it again for each save request? Thanks

 

Note: I have tried replacing SaveRecordRequest with CreateRecordRequest, however the code was not executed once saving, or on any save.

 

Best,

Mohamad

Like 0

Like

10 comments

You can use the CardState to see if the record is in add mode (record is being added, saved for first time) or edit mode:

const mode = await request.$context.CardMode;
if (mode === “add”) {
    //
}

If you need to call some code exactly once when a record is created, I'd suggest moving the whole logic to backend. Specifically EntityEventListener and implement OnInserting or OnInserted methods to call your logic before or after the record is saved

Ryan Farley,

Hey Ryan,

 

Thanks for the reply, however that didn't work. The CardMode returns undefined, and when inspecting it in developer tools (request.$context object) the value is always 'edit' , when inserting the first time or when updating. Is there anything else I can do to fix the issue? Thanks

 

Best,

Mohamad

Yurii Sokil,

Hey Yurii,

 

Thanks for the reply, I have tried moving the logic to backend, however I encountered some issues. The overloaded method OnInserted cannot be async, and therefore I cannot call APIs directly from that method.

There is another option to call asynchronously using this method https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/back-end-development/objects-business-logic#title-2173-11 . However that doesn't solve the problem as if there were any errors when executing the asynchronous code, the record gets saved normally without indicating errors. Its a fire and forget operation and I need something that prevents a record from being inserted if the API call failed. Is there any way I can achieve this? Thanks for help

 

Best,

Mohamad

Mohamad Salhani,

If all you're after is to set up an auto number column, you can use the new auto number column default value. See https://customerfx.com/article/working-with-autonumber-fields-in-creatio/

Ryan

Ryan Farley,

No, so basically I need to populate a field once a record is created, and the value comes from an external API that I have to call

Ryan Farley,

Thanks for the support, I was finally able to solve it by checking the createdOn and modifiedOn dates for the record and see if they are equal, this way I can identify if the record was added for the first time or not. 

Thanks again!

Hi Mohamad, 
You can use AsyncPump.Run() to call async methods synchronously in your event listener. Also you can override OnInserting rather than OnInserted so your logic is called before the record is actually saved. 

Yurii Sokil,

Hey Yuri,

 

Thanks for the reply! It did work however I have a question. How can I pass arguments to the method passed in AsyncPump.Run() ? 

I have this code, but I can't pass arguments to the method.

 

[EntityEventListener(SchemaName = "UsrPetolTest")]
public class CustomEntityEventListener : BaseEntityEventListener
{
    public override void OnInserting(object sender, EntityBeforeEventArgs e)
    {
        base.OnInserting(sender, e);
 
        var entity = (Entity)sender;
        var userConnection = entity.UserConnection;
 
        AsyncPump.Run(testing);
 
    }
 
    private async void testing()
    {
        try
        {

 

Best,

Mohamad

Show all comments

आप इनमें से किसी भी चैनल का उपयोग करके शॉप्सी ग्राहक सहायता टीम तक पहुँच सकते हैं 0 908-8566-267✅और जितनी जल्दी हो सके अपनी शिकायत दर्ज करें।

Like 1

Like

0 comments
Show all comments

Hi Community,

I’m trying to set up global search using Docker, following the documentation. However, when I attempt to run the containers for the global search service components (see image below)

 

I encounter the following error:

 

Does anyone know what might be causing this error and how to resolve it?

Thank you!

Like 0

Like

0 comments
Show all comments

Hello Community,

 

I have created a custom page as shown below and added a button to the top bar.

 

When adding a new record, I want to hide the 'Add to Timesheet' button.

 

I want to learn, how to define the method and Method Calling in UsrTasks_FormPage in schema Designer.

UsrTasks_FormPage  Schema:

 

define("UsrTasks_FormPage", /**SCHEMA_DEPS*/[]/**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
 
    var IsVisible = function() {
        //Logic is to Hide the Button on New Reacord Creation
    };
    return {
     viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
                   {
                "operation": "insert",
                "name": "AddToTimesheet",
                "values": {
                    "type": "crt.Button",
                    "caption": "#ResourceString(AddToTimesheet_caption)#",
                    "color": "primary",
                    "disabled": false,
                    "size": "large",
                    "iconPosition": "only-text",
                    "visible": { bindTo:  "IsVisible" },
                    "clicked": {
                        "request": "crt.CreateRecordRequest",
                        "params": {
                            "entityName": "UsrTimesheet",
                            "defaultValues": [
                                {
                                    "attributeName": "UsrProject",
                                    "value": "$PDS_UsrProject_yuj01i4"
                                },
                                {
                                    "attributeName": "UsrTask",
                                    "value": "$Id"
                                }
                            ]
                        }
                    },
                    "clickMode": "default"
                },
                "parentName": "ActionButtonsContainer",
                "propertyName": "items",
                "index": 0
            }
     ]/**SCHEMA_VIEW_CONFIG_DIFF*/,
        viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
        modelConfigDiff: /**SCHEMA_MODEL_CONFIG_DIFF*/[]/**SCHEMA_MODEL_CONFIG_DIFF*/,
        handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
        converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
        validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
    };
});

 

 

Regards,

Ajay K

Like 0

Like

4 comments
Best reply

If you're wanting to wire up code to run when the button in clicked, see this article: https://customerfx.com/article/adding-a-button-to-execute-custom-code-on-a-creatio-freedom-ui-page/

As for the visible property, using {bindTo: "something"} doesn't work for Freedom UI pages (that is for classic). Instead you'd add an attribute and bind it using "$AttributeName", then set that attribute elsewhere like in the model init request. 

Using attributes: https://customerfx.com/article/using-custom-attributes-on-a-creatio-freedom-ui-page/

Using the model init handler: https://customerfx.com/article/waiting-for-model-to-be-ready-and-loaded-in-the-crt-handleviewmodelinitrequest-on-creatio-freedom-ui-pages/

This article shows how to make something visible or not based on if the user is a member of a role: https://customerfx.com/article/showing-or-hiding-a-field-if-the-current…

Ryan

You can choose the visibility to "visible": { bindTo:  "IsVisible" } and add the conditions if needed:

isVisible: function() {
             if ( ---- )  
                     return true;
             return false;
}
 
OR
 
showButton: function() {
			this.callParent();
			this.set("isVisible", false);
			},

Best regards, Anhelina!

Anhelina,

Could you please clarify how to define the function in the schema?  

Is there any reference how to define the Functions in "ClientUnitSchemaDesigner". 

If you're wanting to wire up code to run when the button in clicked, see this article: https://customerfx.com/article/adding-a-button-to-execute-custom-code-on-a-creatio-freedom-ui-page/

As for the visible property, using {bindTo: "something"} doesn't work for Freedom UI pages (that is for classic). Instead you'd add an attribute and bind it using "$AttributeName", then set that attribute elsewhere like in the model init request. 

Using attributes: https://customerfx.com/article/using-custom-attributes-on-a-creatio-freedom-ui-page/

Using the model init handler: https://customerfx.com/article/waiting-for-model-to-be-ready-and-loaded-in-the-crt-handleviewmodelinitrequest-on-creatio-freedom-ui-pages/

This article shows how to make something visible or not based on if the user is a member of a role: https://customerfx.com/article/showing-or-hiding-a-field-if-the-current…

Ryan

Ajay,

Ryan is right. Suggested method works for ClassicUI but doesn't work with Freedom UI. The way to use visible property has changed. You can check the instructions from the Academy "Hide the feature on a page behind access permissions"

Show all comments

Hi community,

 

I developped package A and package B.

The package B depends on package A.

In the package A I configured a translation for the field TableA.column1.

In the package B I replaced the translation for the field TableA.column1.

Is it possible to restore the default translation set up in package A?

 

 

Like 0

Like

4 comments

Hello,

 

If you have these translations in package A, yes, you can delete the replaced data from package B and the translations from package A will be displayed.

Kalymbet Anastasia,

Thank you Anastasia.

Do you suggest removing the  replacing "client module" from package B?

If so, I would lose my customizations such as fields added

Hello,

 

All translations are stored in the Translation section. If I understood you correctly, they have recently been changed.

If they were simply changed and are not stored in package A, you won't be able to restore them.

 

In the section, these translations are the same for all packages.

https://academy.creatio.com/docs/8.x/no-code-customization/customization-tools/custom-localization/localize-ui-via-the-[translation]-section

Hi,

when I access to translation page on my laptop the application hangs up, so I can't use it

Show all comments

Hi I have faced with issue, that I want to add a gif of a loader to the left side of the caption to inform  user that this field is calculating and change it depending on its content For example if it is empty there should be loader gif if it is not it should be like a green tick.

 

Let's say I have already added MyIcon.png and I have field with this data:

 

{
				"operation": "insert",
				"name": "AgbRegisterFormMessage",
				"values": {
					"layout": {
						"colSpan": 23,
						"rowSpan": 1,
						"column": 1,
						"row": 1,
						"layoutName": "AgbIssuanceTabGridLayout"
					},
					"bindTo": "AgbRegisterFormMessage",
					"enabled": false
				},
				"parentName": "AgbIssuanceTabGridLayout",
				"propertyName": "items",
				"index": 3
			},

 

Like 0

Like

1 comments

Hello Behruzbek Mardonqulov,

Thank you for your question. Could you please provide more details to your question: like what business logic should this perform, what exactly you cannot achieve etc. I would like to help, but i do not think that i fully understand your question.

Show all comments

Hello, community,

I am running a business process, but after 100 iterations, the process stops, and I get this error: 'Operation interrupted to prevent recursive execution. The maximum allowed background recursion depth of 100 has been exceeded while performing these operations.'
I researched the issue and adjusted the 'Maximum Number of Repetitions' in the business process configuration, as well as a system setting called 'MaxProcessLoopCount.' However, I am still encountering the same error.

Like 0

Like

1 comments

Good day,

The issue you're encountering is related to the number of records being passed to the subprocess. Here are some suggestions for resolving this situation:

1. Add or adjust recursion trigger conditions:
   - For instance, if the trigger is based on changes to the `Contact.Age` field, consider adding a condition to ensure the age is not empty before initiating recursion.

2. Redesign the process to avoid recursion:
   - Replace recursion with iteration: Instead of processing records one by one with recursion, you can read and process multiple records in a sequential manner, ensuring that you do not handle a new record until the current one is fully processed.
   - Consolidate changes into a single process: Rather than reacting to various changes across different processes, use one process to handle all necessary changes at once. For example, initiate triggers in a single business process (BP) with all modifications related to a specific entity, which helps in minimizing and managing recursion more effectively.

It is crucial to first review the process logic with the above suggestions, as increasing the `MaximumBackgroundRecursionDepth` parameter could lead to application performance issues, such as slowing down or exhausting server memory, which might result in application restarts or stops.

In your system, the `MaximumBackgroundRecursionDepth` parameter is currently set to 100 (default is 100). The issue arises when the number of subprocess calls exceeds this value.

To address this problem, you may need to increase the `MaximumBackgroundRecursionDepth` parameter to accommodate all records, rather than only the initial 100.

Regards,
Orkhan

Show all comments

Can I combine the Result from business process and the data from object in the same report?

Like 0

Like

1 comments

Hello,
 

It is not possible to insert data from the process directly into the report, as the report uses information obtained from columns/related objects.
 

However, you can add an additional column at the object level (or create an object that has a connection to the record, depending on the task) and include it in the report template. 

Before generating the report element, you can fill this field(s) with values generated during the process.
 

After generating the report, you can clear this column if needed. This way, during the execution of the business process, you will fill the column with the results of the business process, generate the report, and thus the process data will be reflected in the report. Afterwards, you can clear the column if necessary.
 

I hope this helps! Thank you for reaching out!

Best regards,
Pavlo!

Show all comments