back to top

Waiting for the Model to be Ready and Loaded in the crt.HandleViewModelInitRequest on Creatio Freedom UI Pages

A common frustration for adding code in the init requests on a Freedom UI page is that the crt.HandleViewModelInitRequest request often doesn’t have the values on the page loaded yet, or if setting values, they get overwritten as the page loads the defaults for everything (which might be a default causing values you’ve set to be lost). This article will show how to wait for the model to be completely loaded and ready before you proceed with reading or setting any values for the page.

The page’s init request typically looks like this:

{
	request: "crt.HandleViewModelInitRequest",
	handler: async (request, next) => {
		// do stuff
		return await next?.handle(request);
	}
}

The problem is that if you attempt to read any page attributes they are likely (definitely) not yet loaded at this point. Also, if you set page values here, they will get overwritten as the page is initialized when the record is loaded (which is also the case for a “new” record as well). Creatio states that this was not technically intended to be used as an equivalent of onEntityInitialized (from classic pages), however there has not been any other options to be used, leaving this as the only choice.

In the past, I’ve used some hacks, such as using setTimeout to delay things and allow them to load. However, in recent versions (as of 8.1.3 and higher) you can subscribe to all the model events on the page and then wait for the model to be loaded before you proceed. You can subscribe to all the model events using the following:

{
	request: "crt.HandleViewModelInitRequest",
	handler: async (request, next) => {
		await next?.handle(request);

		request.$context.events$.subscribe((async (evt) => {
			// use evt here to get state
		}));
	}
}

Subscribing to this will give us a lot of different event details. The ones we are after are the following:

  • evt.type = A type of “finish-load-model-attributes” will let us know that the model is finished loading (note this event happens many times for each attribute)
  • evt.payload = The payload will include the attributes that have been loaded so far. Meaning, to see if “UsrName” is loaded, we can simply check if evt.payload.UsrName exists yet. Note, that this will only have values that have been added to the page, not other column values not added to the page.

So, if in our init request we want to get the record’s Id value and UsrName column, we would listen for that using the code below. Additionally, it might be good to also check which mode our page (model) is in. There’s a few ways to check this, but we’ll use the request.$context.getPrimaryModelMode() function, which will give us “create” for add mode, or “update” for edit mode.

{
	request: "crt.HandleViewModelInitRequest",
	handler: async (request, next) => {
		await next?.handle(request);

		request.$context.events$.subscribe((async (evt) => {
			const modelMode = await request.$context.getPrimaryModelMode();
			
			if (modelMode === "update" && evt?.type === "finish-load-model-attributes" && evt?.payload?.UsrName && evt?.payload?.Id) {
				// we can now get the values since they are now loaded
				const recordId = await request.$context.Id;
				const name = await request.$context.UsrName;
			}
		}));
	}
}

In the above code, we’re receiving the model events and waiting for the following conditions to be true:

  1. The page is in “update” mode (meaning we’re editing a record)
  2. The model event type is “finish-load-model-attributes”
  3. The event payload contains the attributes that have been loaded in the model. We can use this to check of the attributes we want to read are loaded (in this case, Id and UsrName). NOTE: The evt.payload does NOT contain the actual values of the fields. It will contain a value of true if the column has been loaded in the model.

Or similarly, to set values if the page is in add mode:

{
	request: "crt.HandleViewModelInitRequest",
	handler: async (request, next) => {
		await next?.handle(request);

		request.$context.events$.subscribe((async (evt) => {
			const modelMode = await request.$context.getPrimaryModelMode();
			
			if (modelMode === "create" && evt?.type === "finish-load-model-attributes" && evt?.payload?.UsrName) {
				request.$context.UsrName = "New record"
			}
		}));
	}
}

Even though we’re in add (create) mode and not wanting to read a value from an attribute on the page, we still need to check that the field(s) we’re setting are loaded or they will get overwritten when the “new” (or empty) record is loaded.

NOTE: I am hopeful that this approach is only temporarily needed. I am expecting that at some point we’ll have a proper request for when the model is fully loaded. As you would expect, using this approach could become tedious since you need to check for every field you’re setting or reading. My expectation is that a future version of Creatio will have a request specifically for what we’ve used onEntityInitialized for in classic pages. At least until that time, this approach will let us handle this event without resorting to unnecessary hacks.

Contact Customer FX for your CRM project
We let our expertise speak for itself - let us know how our all-star team can help on your CRM project
About the Author
Ryan Farley
Ryan Farleyhttps://customerfx.com/article/author/ryanfarley/
Ryan Farley is the Director of Development for Customer FX and creator of slxdeveloper.com. He's been blogging regularly about SalesLogix, now Infor CRM, since 2001 and believes in sharing with the community. His new passion for CRM is Creatio, formerly bpm'online. He loves C#, Javascript, web development, open source, and Linux. He also loves his hobby as an amateur filmmaker.

2 COMMENTS

  1. Hi Ryan, great article as always!
    I recently had to deal with this really annoying behavior and I also looked for a sort of “workaround” without using the timeouts…

    The solution I found is the following:
    1. I set the attributes normally in the HandleViewModelInitRequest
    2. I reset the “old” values ​​after Creatio overwrites them in the HandleViewModelAttributeChangeRequest, like this:

    //workaround to avoid page resetting values to null (at start)
    if (request.silent === true && request.value === null) {
    	const globalCustomAttributes = ["firstAttribute", "secondAttribute"];
    	if (globalCustomAttributes.includes(request.attributeName)) {
    		request.$context[request.attributeName] = request.oldValue;
    	}
    }

    What do you think about this approach?

    PS: If the attribute type is text, the check that needs to be done will be:
    request.value === “”

  2. Thanks, this was useful. I found I often needed to unsubscribe once the ID had loaded

    const sub = request.$context.events$.subscribe((async (evt) => {
    if (evt?.type === “finish-load-model-attributes” && evt?.payload?.OmniChatDS_Id ) {

    //unsubscribe when ID loaded
    sub.unsubscribe();

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Building AI-Powered Workflows in Creatio Without Writing Code

See how Creatio can combine AI with no-code business processes to qualify, summarize, and route incoming leads while keeping your existing business rules and human oversight in place.

AI Readiness Checklist for CRM Teams: Is Your CRM System Ready for AI?

Before using AI in Creatio, make sure your CRM data, users, processes, and automation foundation are ready. Use this practical AI readiness checklist for CRM teams.

Build Your Creatio AI Skills with the 2026 AI Summer Program

Join Creatio’s free 2026 AI Summer Program to learn how to identify, build, deploy, and manage AI agents.

Creatio 10x Is Coming: Join the Webinar to Explore the Future of AI-Native CRM

Learn what's new in Creatio 10x and how AI-native CRM, agentic AI, and no-code automation are shaping the future of customer relationship management. Join the upcoming webinar and discover what's next.

Creatio Unlimited Pricing Explained: AI Packages, Costs, Pros & Cons

Learn what Creatio’s new Unlimited pricing model includes, what it doesn’t include, how AI Action packages work, and the pros and cons for businesses evaluating Creatio.

Related Articles

Building AI-Powered Workflows in Creatio Without Writing Code

See how Creatio can combine AI with no-code business processes to qualify, summarize, and route incoming leads while keeping your existing business rules and human oversight in place.

AI Readiness Checklist for CRM Teams: Is Your CRM System Ready for AI?

Before using AI in Creatio, make sure your CRM data, users, processes, and automation foundation are ready. Use this practical AI readiness checklist for CRM teams.

Build Your Creatio AI Skills with the 2026 AI Summer Program

Join Creatio’s free 2026 AI Summer Program to learn how to identify, build, deploy, and manage AI agents.

Creatio 10x Is Coming: Join the Webinar to Explore the Future of AI-Native CRM

Learn what's new in Creatio 10x and how AI-native CRM, agentic AI, and no-code automation are shaping the future of customer relationship management. Join the upcoming webinar and discover what's next.

Related Videos