Hello Community,

The scenario is very simple. 

We are in the Account form page. The account form page has three lookup fields (Type, Category, Primary Contact) We want to filter the Primary Contact based on the (Type and Category). How can this be achieved in freedomUI. Any code example?

Greetings

Sasor

Like 0

Like

1 comments
Best reply

If the lookup is a dropdown lookup (not opening the selection window) this approach can be used to filter it via code: https://customerfx.com/article/dynamically-filtering-a-lookup-on-a-creatio-freedom-ui-page/

For filtering a lookup as a selection window, use the approach here (see response from Harvey): https://community.creatio.com/questions/crtloaddatarequest-does-not-seem-trigger

Note, since that post, the "crt.OpenLookupPageRequest" request has been replaced by the new request "crt.OpenSelectionWindowRequest", so use this new request name instead of what is listed in that post)

Ryan

If the lookup is a dropdown lookup (not opening the selection window) this approach can be used to filter it via code: https://customerfx.com/article/dynamically-filtering-a-lookup-on-a-creatio-freedom-ui-page/

For filtering a lookup as a selection window, use the approach here (see response from Harvey): https://community.creatio.com/questions/crtloaddatarequest-does-not-seem-trigger

Note, since that post, the "crt.OpenLookupPageRequest" request has been replaced by the new request "crt.OpenSelectionWindowRequest", so use this new request name instead of what is listed in that post)

Ryan

Show all comments

Hi,

 

I want to make a validator that endDate cannot be erlier than leave startDate, in endDate field in viewModelConfigDiff,

Expectation:

 

My Code:

 

"PDS_UsrLeaveEndDate_quo1xia": {
	"modelConfig": {
		"path": "PDS.UsrLeaveEndDate"
	},
	"validators": {
		"MySuperValidator2": {
			"type": "usr.FutureDateValidator2",
			"params": {
				"message": "#ResourceString(EndDateWarning)#",
				"startDate": "PDS_UsrLeaveStartDate_apq3vdm"
			}
		}
	}
}

 

   "usr.FutureDateValidator2": {
                validator: function (config) {
                    return function (control) {
                        let value = control.value;
                       let startDate =  config.startDate;
                        let valueIsCorrect = value > startDate;
                        var result;
                        if (valueIsCorrect) {
                            result = null;
                        } else {
                         console.log(startDate);
                         console.log(value);
                            result = {
                                "usr.FutureDateValidator2": { 
                                    message: config.message
                                }
                            };
                        }
                        return result;
                    };
                },
                params: [
                    {
                        name: "message"
                    },
                 {
                        name: "startDate"
                    }
                ],
                async: false
            },

 

But, value of startDate from the params is a String, how to get the actual value?

 

Thank you

Like 0

Like

1 comments

Currently, you cannot pass the value of another field to a validator, this function is still under development. However, you can write something similar using global variables as described in this discussion.

Show all comments

i have 2 look up value for status look up attribute i want to make the status be "Achieved" if the proggress is 100 else will be "not Achieved" i use this code but not work can you help me?
if (request.attributeName === 'PDS_UsrProgress_ws4dy5x') {         // or Progress changed
               var progress = await request.$context.PDS_UsrProgress_ws4dy5x;
               if (progress == 100) {
                                 request.$context.PDS_UsrStatus_qlsxa3e = "Achieved";
               } else {
                                 request.$context.PDS_UsrStatus_qlsxa3e =" Not Achieved" ;
               }

Like 1

Like

3 comments

A lookup’s value is an object with a value (the Id) and displayValue (the text).

You’ll set it using:

request.$context.PDS_UsrStatus_qlsxa3e = {
    displayValue: "Achieved",
    value: TheIdHere
}

thanks Ryan Farley, i try using only id like this request.$context.PDS_UsrStatus_qlsxa3e = "537a92e0-e2bf-494a-913f-3da91eb62e46", and its worked, you think is okay i just do this or use what you give? what do you think that be the best use?

 

Ghifari Zakaria Ramadhan,

Better to compare with value as Ryan showed than object with Id

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

Hi Community,
Can you provide a snippet example, on how we can hide a Detail (list) if the List contains no data (records)?

Thank you

Sasori

Like 4

Like

3 comments
Best reply

This can only be done with code. A combination of doing some model queries to check for records that would be in the list, then using an attribute bound to the visible property of the list to set as true/false based on the results of the query. 

Using the model to query data: https://customerfx.com/article/querying-data-using-filter-conditions-vi…

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

Using the init to execute the above code when the page loads: https://customerfx.com/article/waiting-for-model-to-be-ready-and-loaded…

Ryan

Hi Community,

Any remark on this one?

This can only be done with code. A combination of doing some model queries to check for records that would be in the list, then using an attribute bound to the visible property of the list to set as true/false based on the results of the query. 

Using the model to query data: https://customerfx.com/article/querying-data-using-filter-conditions-vi…

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

Using the init to execute the above code when the page loads: https://customerfx.com/article/waiting-for-model-to-be-ready-and-loaded…

Ryan

Hello,
 

Unfortunately, this task cannot be implemented using standard methods.

 Ryan has provided helpful recommendations that will assist you with implementation through development methods.
 

Additionally, we have registered a task for the development team to add such functionality in future releases.

Best regards,
Pavlo

Show all comments

Hi community, 

Where can I find the source code responsible for this checkbox (Make the list editable). 

I want to make this detail editable only in one section. Here is my use case : I'm using this detail in two sections A and B. In section A, I want the detail to be editable like this : 

 

But in section B, I don't want this behavior (checkbox must be unchecked) like this : 

Like 0

Like

4 comments

You should create 2 separate details. And add them to the separate edit page for section A and for section B.

Thanks Antonii, isn't there any other way than creating two details ? 

Ismail el lahya,

This is the best way to perform this task

Antonii Viazovskyi,

Thank you!

Show all comments

Is it possible to intercept using some request handler the event when a user clicks on the green "Complete" button on a Next Steps tile? This is the button in the "next-step-tile-actions" div on the page which only appears when you hover over the next step tile:

 

It would be vey helpful to be able to run some custom code when this button is clicked - in our case, we need it to save the main page record before actioning this next step, as completing the next step might automatically transition the Lead to the next stage, losing any data entered by the user.

Like 220

Like

6 comments

None of the following handlers are triggered by clicking this button, maybe I've missed some candidates but these are the ones I've tried so far:

crt.ChangeNextStepsStateRequest

crt.OpenPageRequest

crt.UpdateRecordRequest

crt.CreateRecordRequest

Also tried "brute forcing" it by overriding every handler I could find in the Creatio code, but literally nothing fires when clicking that button! Not even something like the page's crt.HandleViewModelPauseRequest (since it's a modal popup, I guess the full page doesn't actually pause like it would when navigating to a another page through clicking a lookup for example). Hopefully I've missed something, triggering some action on clicking that button would be useful.

Any thoughts/knowledge on how such a thing could be achieved?

Hi Harvey! 

 

Unfortunately, at the moment, there is no way to intercept the event of clicking on the Next-steps tile buttons. This button can call different requests depending on the type of tile, and these requests are called without the view model context, which will not allow us to intercept them from the card and use them to save card data.

 

We have registered your idea, and the R&D team has already planned the task for this improvement - they will create a special output event for the Next-steps component. This functionality will be available in future releases.

 

Thank you for making our product better!

 

Best regards,

Natalia

Thank you for the information Natalia, this would be a welcome improvement!

Hi Natalia, is there any expected timeline for this improvement known yet? Do you have a reference for the planned task for later follow-up?

Show all comments

I tried returning false and not calling next?.handle(request), but the record still seems to get saved. In Classic UI it was possible to prevent saving by not calling the this.callParent method, which I believe is somewhat analogous to the next?.handle(request), but I guess not perfectly? Maybe I'm missing something.

Like 1

Like

1 comments
Best reply

Hello Harvey,

It is possible, and you do it in the right way as I can see from the description. To prevent saving you have to declare this handler in the scheme and simply do not call next?.handle(request). 

Hello Harvey,

It is possible, and you do it in the right way as I can see from the description. To prevent saving you have to declare this handler in the scheme and simply do not call next?.handle(request). 

Show all comments

I'm looking to trigger page data validation in a specific circumstance from code. I've found that you can use

request.$context.validate()

within client event handlers to trigger the OOTB fields validation for the page, but this just returns an object representing any/all errors in validation for the data. What would make sense to do in our use case after that would be to trigger the NotifyService message you usually see when saving fails due to such validation checks, but I can't see how to trigger it/how to fetch the string that should be shown in the message. I located a method that looks like it is performing this task for the OOTB save validation, called getValidationErrorMessage, which would be passed the request context and the error object returned by the validate function, but this method doesn't seem to be available for use.

 

Has anybody had any luck with triggering validation in Freedom UI and then displaying the OOTB message based on that validation result? Any help would be greatly appreciated. We're currently running on 8.1.0

Like 2

Like

4 comments

Hello,

If I'm not mistaken, you can use simple OOTB validation that is described here https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platfor…

Hi Dmytro,

 

This doesn't give us a way to trigger the validation manually though unfortunately. What we were trying to achieve was to show the validation message to users without saving/trying to save the record at that point in time. We ended up making our own very basic error message that shows the results returned by

request.$context.validate()

if there are any and stops the user progressing in our custom path, but it would be good to be able to tap into the OOTB error toast message so it's a little more detailed and polished.

Harvey Adcock,

 

Hello! 

Unfortunately, so far, we don't have the functionality to trigger the OOTB validation snackbar-message without saving /trying to save the record. 

We have registered your suggestion, and our R&D team will consider implementing it in future releases.

Thank you for making our product better!

 

Best regards, 

Natalia

Harvey Adcock,

Dear Harvey,

 

See this community article, I think it could help you to answer your question https://community.creatio.com/questions/dynamic-parameter-validator-freedom-ui

 

Regards,

Julio

Show all comments

Is there any way to undo/cancel a change that triggers the crt.HandleViewModelAttributeChangeRequest handler? The use case is that a field is set in the crt.HandleViewModelInitRequest handler, but this setting of the value gets immediately overwritten by the OOTB system that sets up the page it seems. So I would like to be able to conditionally cancel the setting of this field by the page. Any help would be greatly appreciated. We're currently on 8.1.0

Like 1

Like

4 comments

Hi Harvey,

 

We can create an attribute to store a value that you want to set in HandleViewModelInitRequest. Then, in HandleViewModelAttributeChangeRequest, we can check if the current field value matches the one you previously set. If it does not match, we can assign the stored value to it. This way, we ensure that the desired value is assigned to the field.



In the given example, we have created an attribute named "UsrInitialValue".

viewModelConfig: /**SCHEMA_VIEW_MODEL_CONFIG*/{
			"attributes": {
				"StringAttribute_ljc6yh6": {
					"modelConfig": {
						"path": "PDS.UsrTestString"
					}
				},
				"UsrInitialValue": {}
			}
		}/**SCHEMA_VIEW_MODEL_CONFIG*/,



This attribute is used to store a specific value that we set during the initialization process. In the crt.HandleViewModelInitRequest handler, we set a value for the request.$context.UsrInitialValue. And in crt.HandleViewModelAttributeChangeRequest, we check if the current field value matches the value we set previously in the request.$context.UsrInitialValue. If they don't match, we update the field with the new value.

 

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "crt.HandleViewModelInitRequest",
				handler: async (request, next) => {
					request.$context.UsrInitialValue = "testInit";
					request.$context.StringAttribute_ljc6yh6 = await request.$context.UsrInitialValue;
					return next?.handle(request);
				}
			},
 
			{
				request: "crt.HandleViewModelAttributeChangeRequest",
				handler: async (request, next) => {
					var srtValue = await request.$context.StringAttribute_ljc6yh6;
					var initVal = await request.$context.UsrInitialValue;
					if (request.attributeName === 'StringAttribute_ljc6yh6' && srtValue != initVal) {
						request.$context.StringAttribute_ljc6yh6 = initVal;
					}
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

 

Artem Smyrnov,

 

I think this would prevent any modification to the data, including intended changing by the user or system. Obviously it could be changed to add some more conditions, but really the main thing we want/frequently need is for the crt.HandleViewModelInitRequest request to be able to initialise a value and not be overwritten by the standard page loading stuff (loading default values for the entity, clearing out the field where there are no default values etc). I'm pretty sure this was possible in Classic UI, it just doesn't seem to be currently in Freedom UI without some pretty nasty hacks.

Harvey Adcock,

There is no logic that could be used to revert changes to the column value that were done by the handler.

As a solution, you need to create a column that will not use any other handler and set the value using your custom handler. This will prevent the value from being overwritten by other handlers or custom logic.

We have a workaround in place, but this capability has been required a few times - it would be good if Creatio supported setting values on the page in the init handler (or some other handler, maybe a new initvalues handler or something) since per-page default values is often required.

Show all comments