Время создания
Filters
How_to_detect_modified_fields_before_save_and_conditionally_block_save?

Hi Community,

I am working with Creatio Freedom UI (8.x) and I have the following validation requirement.

Scenario

I have two sets of fields:

  • Set A → A group of key fields (for example: Field1, Field2, Field3)
  • Set B → A group of  fields (for example: ApprovalReason, Comments)

Requirement

  1. If any field from Set A is modified, then:
    • I need to check whether all fields in Set B are filled.
    • If any field in Set B is empty → block save and show validation message.
  2. If the user modifies fields that are NOT part of Set A:
    • Save should be allowed normally.

My Questions

  1. In Freedom UI, is there any built-in attribute that stores the list of changed/modified fields before saving the record?
  2. If not, what is the recommended approach to detect whether specific fields were modified?
  3. Should this logic be implemented:
    • On client side using HandleViewModelAttributeChangeRequest?
    • Or in backend using the EntitySaving event and comparing old/new values?
  4. Is there a supported way to retrieve changed columns on the backend instead of manually comparing values?

I would like to follow the recommended and supported best-practice approach.

Thanks in advance!

Like 0

Like

0 comments
Show all comments

Dear colleagues,

I have a Freedom UI page (Creatio v8.3.2.4166) that activates the Save button immediately on load, without any user interaction.

After extensive debugging, I identified three contributing factors:

1. ForwardReference attributes in modelConfigDiff. The page has multiple attributes of type "ForwardReference" resolving data from two related entities. These are all read-only fields. Example:

"NcsRelatedEntityNcsDescription_abc123": {
    "path": "NcsRelatedEntity.NcsDescription",
    "type": "ForwardReference"
}

When these attributes resolve asynchronously after page load, the framework registers them as user changes and sets HasUnsavedData = true.

2. RichTextEditor controls with <strong>needHandleSave: true</strong> — for some reason the page wizard generated them with true by default, even though all of them are readonly and display data from a related entity, not from the current object's own fields. We changed all of them to needHandleSave: false, which helped partially but did not fully resolve the issue.

3. Calculated field handlers. The page has a handler that calculates age from a birth date field (and another similar purpose handlers):

{
    request: "crt.HandleViewModelAttributeChangeRequest",
    handler: async (request, next) => {
        if (request.attributeName === 'PDS_NcsBirthDate_abc123') {
            const birthDate = await request.$context.PDS_NcsBirthDate_abc123;
            if (birthDate) {
                const today = new Date();
                const birth = new Date(birthDate);
                let age = today.getFullYear() - birth.getFullYear();
                if (today.getMonth() < birth.getMonth() ||
                   (today.getMonth() === birth.getMonth() &&
                    today.getDate() < birth.getDate())) {
                    age--;
                }
                request.$context.PDS_NcsAge_xyz789 = age;
            } else {
                request.$context.PDS_NcsAge_xyz789 = null;
            }
        }
        return next?.handle(request);
    }
}

When the page loads with an existing record, PDS_NcsBirthDate_abc123 fires as an attribute change event during model initialization, the handler writes PDS_NcsAge_xyz789, and that write marks the page dirty — even though both values were already saved in the database.

The same pattern applies to a handler that composes a full name from first and last name fields, and to the RichTextEditor ForwardReference fields that display read-only rich content from a related entity.

What we tried:

Approach 1 — Subscribing to events$ in HandleViewModelInitRequest to detect finish-load-model-attributes, setting a window._NcsPage_pageReady flag, and guarding all attribute change handlers behind it. This correctly prevents our own handlers from triggering dirty state, but does not prevent the framework itself from setting HasUnsavedData = true when ForwardReferences resolve.

Approach 2 — Adding a HandleViewModelResumeRequest handler that forces HasUnsavedData = false after the model is ready. This fires too early — ForwardReferences resolve after Resume, so they overwrite the reset.

Approach 3 — Using setInterval (up to 35 cycles × 200ms = 7 seconds) inside the Init handler to repeatedly reset HasUnsavedData = false. This does not work because the request.$context captured in the Init handler closure becomes stale after initialization — Creatio replaces the ViewModel reference, so we are resetting a dead object.

Approach 4 — Intercepting all HandleViewModelAttributeChangeRequest as the first handler in the chain, calling await next?.handle(request) and then forcing HasUnsavedData = false on the fresh request.$context. This works during the initial load phase (while _pageReady = false), but ForwardReferences continue resolving after _pageReady = true, still triggering dirty state.

Approach 5 — Combining Approach 4 with permanent suppression for all known ForwardReference attributes (since they are always readonly):

{
    request: "crt.HandleViewModelAttributeChangeRequest",
    handler: async (request, next) => {
        const result = await next?.handle(request);
        const isForwardRef = request.attributeName?.startsWith('PDS_NcsRelatedEntity');
        if (!window._NcsPage_pageReady || isForwardRef) {
            request.$context.HasUnsavedData = false;
        }
        return result;
    }
}

This still fails — HasUnsavedData keeps flipping back to true after each reset.

Questions:

  1. Is there a supported Freedom UI pattern to prevent HasUnsavedData from being set by ForwardReference resolution on page load?
  2. Is there a lifecycle event or request that fires reliably after all ForwardReferences have fully resolved?
  3. Is there a way to prevent a handler that writes a calculated field (like age from birth date) from marking the page dirty when it fires during initialization?
  4. Is there any way to mark specific attributes as non-dirty-tracking so the framework ignores their changes for save state purposes?

Any guidance from the community would be greatly appreciated. Thank you very much

Regards

Julio Falcón

Like 1

Like

0 comments
Show all comments
AI
creatio.ai
data
security

Hi, 

Could you explain a bit more how the data protection layer works ( as shown on  https://www.creatio.com/ai/ai-trust-and-governance ) ? Does it anonymize data before sending to the LLM ? Is there more documentation about it ? What do we need to configure for custom fields ? How does it handle data in files ?



Does it work such as mentioned below ?



 

Like 0

Like

0 comments
Show all comments

Hi Team,

We are currently using the following server-side code to send Mobile Push Notifications in Creatio:

var userConnection = this.Get<UserConnection>("UserConnection");
var pushNotification = new PushNotification(userConnection);
 
Dictionary<string, string> additionalData = new Dictionary<string, string>();
additionalData.Add("entityName", entityName);
additionalData.Add("recordId", recordIdStr);
 
pushNotification.Send(sysAdminUnitId, title, message, additionalData);

On the mobile side, we are using the standard:

Terrasoft.configuration.PushNotificationReceiver

Now we have a requirement to delete or cancel a previously sent push notification based on:

  • entityName
  • recordId

For example:
When a record is approved or completed, the related push notification should be removed from the mobile device.

However, we understand that Push Notifications are not stored in a database table like System Notifications.

Could someone please clarify If there is a supported way to cancel or remove a specific mobile push notification?

Any guidance or best practice would be greatly appreciated.

Thank you!

Like 0

Like

0 comments
Show all comments
campaign
audience
referrals
Studio_Creatio_enterprise_edition
8.0

Hello, I am building a campaign flow, and need to find a way to trigger an email to refrees' on referral accounts. So the break down is, a referral comes in through a webform, the referral will have the contact and account that referred them in the system. once the referral become an active account i need an email to trigger to the contact that referred them in the first place. How do i set up an email to trigger to that referral

Like 0

Like

0 comments
Show all comments