Hello,

I created a validation for telephone numbers as explained in this article: Implement the validation of a field value on a page | Creatio Academy
For testing purposes, I added it to the notes field on the contacts form, and it works fine.


However, I want to add the validation to the communications options on the left side of the form.
How do I bind the validation in the viewModelConfigDiff?
Also, only communication options of type "phone number" should be validated.

 

Thanks,

Robert

Like 1

Like

3 comments

Hello,

Currently there is no way to add the validator using the regular approach with the validators property on the schema. However you can try adding it using the formControl for the ContactCommunicationOptionsItems (but note that this will be applied for phones, email, skype and web (in other words for all communication options)).

 

How to add the validator using formControl:

 

  1. Implement the same validator on some separate field on the page
  2. Find this validator in the context of the crt.HandleViewModelAttributeChangeRequest request execution (like request.$context._validators["AccountAccountCategory_List.value"][0]), but replace AccountAccountCategory_List.value with your attribute name on the page to which the validator is added. Also make sure array with only one element is returned (since you can have several validators for the same field and the array of validators can contain more than 1 element thus ...["AccountAccountCategory_List.value"][0] can return another validator.
  3. In the context of the crt.HandleViewModelAttributeChangeRequest request (connected to the change of the ContactCommunicationOptionsItems attribute) add the following code:

request.$context.getControl("ContactCommunicationOptionsItems").formControl.addValidators(request.$context._validators["AccountAccountCategory_List.value"][0])
 

But replace equest.$context._validators["AccountAccountCategory_List.value"][0] with the needed validator.

 

This is the only way to add the validator for this CommunicationOptions component (but once again note that this will be added to all the other communication options). 

Oleg Drobina,

thank you for pointing me in the right direction!

However, I can't get it to run...I used the following code, but the validation won't be triggered:

			{
			    request: "crt.HandleViewModelAttributeChangeRequest",
			    handler: async (request, next) => {
					if (request.attributeName === 'ContactCommunicationOptionsItems') {
						const validators = request.$context._validators;
						const telValidator = validators["StringAttribute_cuzyv0b"]?.[0];
						if (telValidator) {
							request.$context.getControl("ContactCommunicationOptionsItems").formControl.addValidators(telValidator);	
						}
					}					
			        return true;
			    }
			}

What's also strange is that when the handler is executed again (after I changed the field value), all properties of the formControl related to validation (asyncValidator, validator, _rawValidators, _rawAsyncValidators) are empty again!

Any idea what could go wrong here?

Thanks,

Robert

 

Robert Pordes,

Unfortunately no, this was the way I used locally and that worked and maybe the difference may arrise in the application version that was used for tests (8.2.2 in my case) or in other handlers maybe. This should be debugged only, there is no other way to identify what's wrong.

Show all comments

I have try to override the save functionality. But, it is not working. Even the 1st console is not working. I have added bindTo in click event in ViewConfigDiff. Pls help with that.

Like 0

Like

4 comments
Best reply

Hello, 

You seem to be mixing things between classic pages and Freedom UI pages. The page you're customizing appears to be a Freedom UI page, which does not support adding methods. The code you've added would work for classic pages, but not on Freedom UI pages. 

Instead, this is done via request handlers on Freedom UI pages. See this link for overriding the save request on a Freedom UI page: https://customerfx.com/article/adding-code-to-the-save-event-of-a-creatio-freedom-ui-page/

Ryan

Hello, 

You seem to be mixing things between classic pages and Freedom UI pages. The page you're customizing appears to be a Freedom UI page, which does not support adding methods. The code you've added would work for classic pages, but not on Freedom UI pages. 

Instead, this is done via request handlers on Freedom UI pages. See this link for overriding the save request on a Freedom UI page: https://customerfx.com/article/adding-code-to-the-save-event-of-a-creatio-freedom-ui-page/

Ryan

Also, as a side note, the code you have in the getActiveCount won't work since ESQ is asynchronous (so the return will happen before the query returns any results), additionally, the results of the query of an ESQ are passed in via a callback function passed as a parameter to getEntityCollection, not returned as a result of calling getEntityCollection.

For a Freedom UI page, I'd use a model load instead of the ESQ since you can await the result, rather than use a callback function. See https://customerfx.com/article/querying-data-using-filter-conditions-via-the-model-class-equivalent-to-enityschemaquery-in-a-creatio-freedom-ui-page/

Ryan

Hi Ryan,

I have added this code in handler, still it's not works for me. Please address, what i missed here.

Revathi,

Can you provide more details by what isn't working?

Show all comments

Does anybody have fairly solid methods of working around Creatio's limitation of not being able to distinguish between zeroes and missing values for number fields? This often comes up in requirements, and I haven't found a workaround that works so well that I always use it.

 

Some methods we've tried/considered:

  • Using Text fields instead of number fields
    • Obvious disadvantage of not having numeric protections/validations, both in the page layer & the backend & database side
    • Values can't be aggregated into KPI widgets/graphs, unless you have some process to copy the number text into a hidden number field...
  • Having a Boolean field for every number field to indicate if it should be null or zero
    • Cumbersome to implement on objects with lots of number fields
    • Field still displays as a zero value unless you add in custom code everywhere it appears
    • BPs or Event Listener code needed to ensure these 2 fields agree, plus logic in the page/integrations needed to set the flags and make the field show nothing when the flag is set

 

Any other workarounds people are using that are effective? Hopefully Creatio will add this capability at some point as it is crucial for having valid data, but it feels like it would require a fairly big change to the platform, so I don't expect we'll get it very soon!

Like 0

Like

3 comments

Hello Harvey,

 

The task is still in progress and the only workaround that currently exists is using the text column instead of a number. In case this number should be processed it can be done using type casting in formulas (or script tasks) of business processes.

 

I've also added your voice to prioritize the problem for our R&D team. Hope this will be implemented soon.

We are also experiencing this issue when searching by dates. For example, 4/5/1967 will generate a hit, but not 04/05/1967.  Interested in being added to any prioritization tickets on this.

 

Anna Pannier,

 

Please create a separate question in the community with a description of how exactly the search is performed and which datatype your current column that stores the date has.

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

Hi community,

Calling a Business process is quite easy in FreedomUI, by adding a button and choosing

Action: Run process.

The problem with this approach is that once the button is clicked, there is no validation happening in the page.

Is there any code snippet or workaround that when clicking a button that runs a business process, prior to the calling of the process a validation(practically a Save) happens?

Sasori

Like 1

Like

6 comments

The only option currently is to wire up code for the button. It would first save the page, then if the save was successful you would execute the process. 

See how to save the page and detect if it was successful here: https://customerfx.com/article/saving-a-page-before-some-action-on-a-creatio-freedom-ui-page/

See how to start the process via code here: https://customerfx.com/article/starting-a-process-from-client-side-code-on-a-creatio-freedom-ui-page/

Ryan

Ryan Farley,

Thanks for the response Ryan. Do you actually have an example on how to integrate within the 'CustomMethod' both crt.SaveRecordRequest and crt.RunBusinessProcessRequest ?

Ryan Farley,

Ryan if im not mistaken, with the suggested approach , every time the user will click the SAVE button, the overriden crt.SaveRecordRequest will be called?

In the first linked example, you would only be running that `usr.CustomCodeRequest` handler when you click your custom button. If you put the code inside the crt.SaveRecordRequest handler, then it would be run every time the user saved the page in some way.

Sasori Oshigaki,

As Harvey mentioned, the code for your button will only execute when the button is clicked, not when the Save is clicked. Your button will also initiate a save and then, if successful and validated (and the save occurred) it will then execute the process. The code from the first article triggers the save to happen and then provides the result. In the article (the first one) the save returns a result, where the code has // save was successful, continue with something else here you'd replace that with the code to start the process (the second article). If needed, you can see how to wire up custom code to your button in this article: https://customerfx.com/article/adding-a-button-to-execute-custom-code-on-a-creatio-freedom-ui-page/

Ryan

Thank you  both Ryan and Harvey! Was able to achieve what i intended!

     {
    request: "so.SaveAndRunBP",
    handler: async (request, next) => {
            const saveRecordRequest = {
            type: "crt.SaveRecordRequest",
            preventCardClose: true,
            $context: request.$context
        };
        if ((await request.$context.executeRequest(saveRecordRequest)))
        {
          const handlerChain = sdk.HandlerChainService.instance;
          const result = await handlerChain.process({
              type: "crt.RunBusinessProcessRequest",
              processName: "SoGenerateContact",
              processParameters: {
                  ContactId: await request.$context.Id,
              },
              $context: request.$context
          });
        }
        return next?.handle(request);
    }
}
Show all comments

Hi,

I often use backend validation in Creatio - I prevent saving a record and throw an exception from an event listener. It works like a charm, but as a result, the end user sees only a toast message, which is small and disappears after a moment, so it's easy to overlook. Is it possible to intercept such an error and display a normal confirmation popup, instead of this one?

It would be great if there is a generic solution, which doesn't require me to change all of my validations.

Like 0

Like

2 comments

Hi Eryk, in your business process you can display a mini page with the process component pre-configured page. 

 

Else you have following component to add in your site:

https://marketplace.creatio.com/template/popup-element-business-processes

 

Hope this helps.

Hello Eryk,
Thanks for your question.

As an alternative you can use websockets to implement your logic. 

Here i created a custom section and a clientMessageBridge as described in this article. In this section i created a Test Field. To subscribe to message broadcasting in the HandleViewModelInitRequest handler i used schema attribute to store a function that will be called whenever a message is published. Also note, that you should unsubscribe from websocket connection when your view is destroyed. To do this please don't forget to implement such logic in HandleViewModelDestroyRequest handler. 

On the form page when user clicks Save button a custom MyCustomRequest handler is called. In this handler i realized the following logic: call a business process (where i pass Test Field value as well as expected business process parameter value) -> if there is no validation error that is passed back from business process (hasValidationErrors property) i call SaveRecordRequest request -> if there is an error - the SaveRecordRequest is not performed.

Also the function that is triggered when a websocket message is broadcasted does open a pop-up which displays error message.

Here is an example:
page designer
handlers
bp

script task

And the outcome:
3
1

2

Hope this helps and let me know if you have any question left.

Show all comments

I have a validator function with the "async" flag set to true.  It is working however the error message is not showing when the record is saved and the validation fails.

		viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[
			{
				"operation": "merge",
				"path": [
					"attributes"
				],
				"values": {
					"UsrCaptainReportsTo": {
						"modelConfig": {
							"path": "UsrYachtsDS.UsrCaptainReportsTo"
						},
						"validators": {
							"CaptainReportsTo": {
								"type": "usr.CaptainReportsTo",
								"params": {
									"message": "'Captain reports to' must be an affiliate in the yacht's affiliates list."
								}
							}
						}
					},
		validators: /**SCHEMA_VALIDATORS*/{
			"usr.CaptainReportsTo": {
				"validator": function (config) {
					return async function (control) {
						var validated;
						validated = false;
						//debugger;
						return validated ? null : { "usr.CaptainReportsTo": { message: config.message } };
					};
				},
				"params": [
					{
						"name": "message"
					}
				],
				"async": true
			}
		}/**SCHEMA_VALIDATORS*/

 

Like 0

Like

1 comments

Hello,

 

We've reproduced the issue in 8.1.3 and the only possible way to use the validator now is to use it synchronously (using "async": false). Our R&D team has created a task to fix this bug in future application releases and took it in progress. Thank you for reporting this issue to us and helping us in making the app better!

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

Hi all,

How to do a validation on the entries when the user clicks the DCM to change status?

If the validation fails, the DCM will remain in the current status.

The business process only checks after an update which is not ideal for validation checking.

Like 0

Like

6 comments

Hi David

 

We've worked around this by creating buttons that trigger processes.

Inside the process the checks are run, and then the state is changed.

 

Rgds,

Luis

Hello,

 

Could you please describe your business task in more detail so we could better understand how exactly you need the system to work?

To accomplish this we store the stage in an attribute and then can revert back if needed. I have an example of this here https://customerfx.com/article/how-to-prevent-users-from-moving-a-case-…

Ryan

Luis Tinoco Azevedo,

Hi Luis,

 

I have thought about this.

However, how to implement this concept if the DCM has many stages?

Do we need to create a button for every stage?

 

David

Ryan Farley,

Hi Ryan,

 

Thank you for the article.

The approach in the article is very neat. It might be the suitable solution to my problem.

I love the articles from customerfx.com.

 

Thanks again.

 

David.

 

Mira Dmitruk,

Hi Mira,

 

Assume the screen below, on a certain condition the "Sales order service" should not be empty before entering the "In progress" status. However, I couldn't set the "required" attribute on the field from the business rule, because the condition is a bit complex.

In this case I need a validator before the status changes to "In progress".

 

David

Show all comments

Hi Community,

 

I am trying to add a field validation via javascript code using the below article.

https://academy.creatio.com/docs/developer/getting_started/develop_appl…

 

While I am trying the validation, I am getting an error in the console as in the screenshot below. It says "Cannot read properties of undefined (reading 'invalidMessage')." I am initiating a null value in the method as described in the above article. What am I missing here? I cannot add validation to any fields because of this error. I have also added my code snippet below.

 

onEntityInitialized: function() {
				this.callParent(arguments);
				this.onBooleanChange();
				this.changeColor();
				this.setYearEnd();
				this.setNumberOfDaysInApplicationCreationStage();
				this.accountHolderValidator();
			},
 
			setValidationConfig: function() {
				this.callParent(arguments);
				//this.addColumnValidator("BEALMDateofBirth", this.dateOfBirthValidator);
				this.addColumnValidator("BEALMAccountHolderType", this.accountHolderValidator);
			},
 
			accountHolderValidator: function() {
				var invalidMessage = "";
				var lead = this.get("BEALMLead").value;
				var scope = this;
				var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
					rootSchemaName: "Lead"
				});
				esq.addColumn("Id");
				esq.addColumn("BEALMIsPAHExist");
 
				var esqFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Id", lead);
				esq.filters.add("esqFilter", esqFilter);
 
				esq.getEntityCollection(function (result) {
					if (result.success) {
						var isPAHExist = result.collection.collection.items[0].values.BEALMIsPAHExist;
						if (isPAHExist == true) {
							invalidMessage = this.get("Resources.Strings.BEALMInvalidAccountHolderMessage");
						}
						else {
							invalidMessage = "";
						}
						return {
							invalidMessage: invalidMessage
						};
					}
				});
			},

 

Please help to resolve this issue.

 

Thank you

Cheers!

Like 0

Like

2 comments
Best reply

There are two issues:

1) You're not including the scope in your ESQ so in the callback it no longer knows what "this" is. Change to this: 

esq.getEntityCollection(function (result) {
    // stuff here
}, this);  // <- notice passing this scope 

2) Regardless of the missing "this" scope, this will not work since the ESQ is asynchronous. You'll need to use asyncValidate instead. I have an article on how to do that here: https://customerfx.com/article/asynchonous-validation-on-pages-in-creat…

Ryan

 

There are two issues:

1) You're not including the scope in your ESQ so in the callback it no longer knows what "this" is. Change to this: 

esq.getEntityCollection(function (result) {
    // stuff here
}, this);  // <- notice passing this scope 

2) Regardless of the missing "this" scope, this will not work since the ESQ is asynchronous. You'll need to use asyncValidate instead. I have an article on how to do that here: https://customerfx.com/article/asynchonous-validation-on-pages-in-creat…

Ryan

 

Hi Ryan,

 

Thank you very much for the support. That worked like a charm.

Show all comments