Hi, 

 

is there a code, script or library or a workaround in freedom UI (not classic) to do a dropdown list with multi select (I am using the new Version: Quantum) 

Like 1

Like

1 comments

Hi,



On normal fields, it's easy to deactivate the ability to create new records for a specific field on a page. But when adding a list pointing to another object, I have not seen the ability to do so .



Am I missing a parameter option or it is not yet possible ?



 

Thanks,



Damien

Like 3

Like

4 comments

Any ideas ? community ? Creatio ?

Hello!

 

Unfortunately, as of now, there is no such possibility.

 

Thank you so much for your idea. We've registered it in our R&D team backlog for consideration and implementation in future application releases. Thank you for helping us to improve our product.

Kyrylo Atamanenko,

Thank you for your input! 

Do you have any guide in the academy to fix this in coding in the meantime ? Because it is an issue that was not existent in Classic UI Details and is quite an issue reported by all our clients....

Show all comments

Is it possible within Freedom UI to trigger a refresh of the Timeline/Feed/Next Steps components using JS? We seem to have an issue where the "Enable live data update" option does not seem to be working in Creatio CRM 8.1 for our Activities on certain pages, and while we've raised a support request for this, we were trying to find a workaround by manually updating the components from code for a specific use case, but we can't see what the data source is called for these types of components. Does anybody know what it would be? I presume refreshing the PDS would refresh them, but this seems heavy handed and might end up with data being lost on the main form page while the data actually being refreshed is just a child entity, so I would expect it to have its own data source.

Like 3

Like

3 comments

+1

Hello Harvey and Damien!

In Freedom UI Pages, the structure of the page is different and along with this a new way to refresh anything on the page. In this article you can find the way to achieve your goal:

https://customerfx.com/article/refreshing-reloading-page-or-list-data-on-a-creatio-freedom-ui-page/

Here's example of handler which you can use:

handlers: /**SCHEMA_HANDLERS*/[
 {
  request: "crt.HandleViewModelAttributeChangeRequest"/* The custom implementation of the system query handler. */
  handler: async (request, next) => {
   await next?.handle(request); 
   if (request.attributeName === 'Your Attribute Name' )
   {
    const handlerChain = sdk.HandlerChainService.instance;
    await handlerChain.process({
     type: 'crt.LoadDataRequest', $context: request.$context,
     config: { loadType: 'reload' },
    dataSourceName: 'Data Source Of Obj You Want To Refresh'
    });   
   }
  }
 },

You may also find this article useful:

https://customerfx.com/article/receiving-server-side-messages-in-a-creatio-freedom-ui-page/

 

Anhelina,

 

How can we find what the data source is for a component like a Timeline or Next Steps component though? The article suggests looking at the modelConfig elements in the page code, but none of these seem to relate to the timeline or timeline tiles. I expect there is some data source being created behind the scenes but finding out what it's called is the main problem for applying the theory of being able to reload anything on the page as is suggested.

 

Many thanks,

Harvey

Show all comments

Hello,

I want to place 2 fields in Flex container, and make first field wider than second one.

But they appearing with equal width.

 

How can I set width of them?



Thank you!

Vladimir

Like 1

Like

2 comments
Best reply

Seems like you might want a grid container (Area from the Layout Elements section of the page designer) within that flex container? These would keep the relative sizes of the 2 fields proportionally the same through resizing. For example, below I added a grid container with 6 columns to the flex container, and set the width of the first field to 4 columns (by clicking & dragging the resizer on it) and the width of the second to 2 columns. Number of columns can be adjusted to allow you to get the ratio you want:

 

Seems like you might want a grid container (Area from the Layout Elements section of the page designer) within that flex container? These would keep the relative sizes of the 2 fields proportionally the same through resizing. For example, below I added a grid container with 6 columns to the flex container, and set the width of the first field to 4 columns (by clicking & dragging the resizer on it) and the width of the second to 2 columns. Number of columns can be adjusted to allow you to get the ratio you want:

 

Harvey Adcock,

That's great! Thank you!

Show all comments

How would we associate page with  a data source ID and load up that data source when the page loads?

 

Currently the Classic UI page opens, but no data is loaded.

Like 0

Like

1 comments

Hello,



Could you please elaborate on your business task with screenshots? 

Show all comments

In a section edit page, we have created custom buttons and have functionalities to hide and show the button. If we refresh the page Button enable/ Disable are working fine

But once we open the edit page, the button visibily/ page opening are not working properly until we refresh the page

we tried  this.reloadEntity(); inside init:function(){} Method.

Please Suggest me how to solve this issue.

Like 0

Like

2 comments

Hello,



Could you please describe in more detail what the problem with the button is when refreshing the page? I mean, how should they work and how do they actually work? If you have a chance, please send screenshots.

I think, this button works only in Page mode. So, you should also add this button to Section. (see more in https://academy.creatio.com/docs/developer/interface_elements/record_pa….)



Kind regards,

Vladimir

Show all comments

Hello everyone,

I'm trying to retrieve information from my apps in Creatio CRM. When I open my Studio, I notice that there's a request that brings me the apps and their respective IDs. It would be incredibly helpful if someone could share how I could do this using OData or if there's a similar schema seems like it's called "Environments"...  or any other method to achieve this. Ideally, I prefer it to be RESTful.

I've attached some photos for reference to illustrate my situation.

Thanks in advance for your help!









Like 0

Like

3 comments

Hello,

 

Try to retrieve information using $metadata.

Kalymbet Anastasia,

Any examples?

Hi,

If I'm not mistaken, you can use this odata request to get the information you need

/0/odata/SysInstalledApp

If this is not what you wanted, please specify what exactly you mean by "apps".

Show all comments

Greetings,



I have a module that I created withing the email app titled "Text Chart List" 





In the design mode, everything in the module looks to be perfect and aligned, but in the preview mode, it looks completely off:





Is there any reason why this is happening? Also, are there any workarounds/solutions that are recommended? Thanks in advance.



Lucas

Like 0

Like

1 comments

Hello, 

 

The display of images on a mobile depends on the template styles. This may be due to the fixed size of the images. Unfortunately, the content designer does not allow you to configure the mobile version separately, so we recommend checking the CSS styles of the content block with these images. The only thing to do here is to experiment with the template itself (width, font, etc. in the block/section/column settings) and see how this is displayed in the mobile app.

 

We have already registered this problem for our development team and the issue has been prioritised thanks to your request. 

You can also contact technical support at support@creatio.com for a more detailed analysis. 

 

 

Show all comments

Hi,

Is there a way to configure what displays in noteworthy events?  I want to hide employee birthdays and only show customer birthdays.

Is there somewhere I can make these changes?

 

Looking forward to any help on this !

 

Thanks!

Like 0

Like

1 comments

Hello Anjum,



You can only disable it for all employee and customer birthdays. 

 

You just need to create a system setting (UseGenerateAnniversaryRemindings) and save it in a disabled state:

Show all comments

How can we apply custom filters on Lookups in Freedom UI? I can see that there is some existence of a filtersConfig potential property for the object passed as the first parameter to executeRequest, but cannot find any examples or information on how this should be configured in Academy or on other Community questions. We are trying to use this to associate records to a parent record using the + button on a Freedom UI "detail" list, but we don't want any records already associated with any parent by foreign key to be eligible for association using the lookup, and also have some other conditions to apply based on the child entity. Our environment is currently on 8.1 Quantum.

 

Here is the relevant excerpt from the handler on our form page, without any filters applied and with the non-relevant logic applied in the afterClosed area removed for brevity:

request.$context.executeRequest({
	type: "crt.OpenLookupPageRequest",
	$context: request.$context,
	entitySchemaName: "Order",
	caption: "Select Quotes to associate with the Lead",
	features: {
		select: {
			multiple: true,
			selectAll: false,
			resultType: 'lookupValues'
		},
		create: {
			enabled: false
		}
	},
	afterClosed: async function(selectedItems) {
		// logic here
		return next?.handle(request)
	}
});

 

Like 0

Like

5 comments
Best reply

Hello,

Here is an example of OpenLookupPageRequest with a filtersConfig.

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenLookupPageRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: (result) => {
							alert(result?.displayValue ?? '');
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

If you don't know how to build a proper filter here is a small tip. On a Freedom UI page add a list with the object you want to filter. In this list add a static filter with a condition you want to apply to a OpenLookupPageRequest and save it. As a result, in the code of this page, you can find the full filter code, all you need to do is to replace "MyFilter" with it.

Hello,

Here is an example of OpenLookupPageRequest with a filtersConfig.

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenLookupPageRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: (result) => {
							alert(result?.displayValue ?? '');
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

If you don't know how to build a proper filter here is a small tip. On a Freedom UI page add a list with the object you want to filter. In this list add a static filter with a condition you want to apply to a OpenLookupPageRequest and save it. As a result, in the code of this page, you can find the full filter code, all you need to do is to replace "MyFilter" with it.

Question on OpenLookupPageRequest. In an edit scenario, could you pass the already selected options so that they appear already selected in the lookup list?

You can use the option selectionState to predefine selected rows, which will be pre-selected

type: "crt.OpenLookupPageRequest",
	...
	selectionState: {
		type: 'specific',
		selected: [
			'9d06bf9f-eb7a-4849-b83d-cbba994f185d',
			'49ba9a9e-2e28-48cb-b1bc-81b7871acb9d',
		],
	},

 

Dmytro Vovchenko,

 

Those are really useful, are there any other parameters that can be passed to the newly opened lookup page? I'm currently looking for a way to automatically set the initial search value of the lookup window, but I'm sure there are many other undocumented useful parameters like the selectionState that can be passed to a lookup page when opening it. A generic way to pass data into the page would be great!

 

I looked into passing a defaultSearchValue parameter into the request, but it didn't seem to affect the modal lookup.

Harvey Adcock,

 

Hello,

 

Here is all the available documentation we have:

 

Lookup window example:

In order to open the lookup window, you have to use crt.OpenSelectionWindowRequest

/**
 * @publicApi
 */
@CrtRequest({
    type: 'crt.OpenSelectionWindowRequest',
})
export class OpenSelectionWindowRequest extends BaseRequest {
    public itemAttributeName?: string;
    public itemsAttributeName?: string;
    /**
     * @publicApi
     */
    public entitySchemaName?: string;
    /**
     * @publicApi
     */
    public schemaName?: string;
    /**
     * @publicApi
     */
    public filtersConfig?: FiltersConfig;
    /**
     * @publicApi
     */
    public features?: PageLookupFeatures;
    /**
     * @publicApi
     */
    public selectionState?: SelectionState;
    /**
     * @publicApi
     */
    public afterClosed?: (result: SelectionWindowResult) => void;
    /**
     * @publicApi
     */
    public caption?: LocalizableString;
}

Add the following code to your custom handler:

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenSelectionWindowRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: async (result) => {
							if (!result.canceled) {
								const lookupValues = await result.getLookupValues();
								const value = lookupValues[0];
								if (value) {
									alert(value?.displayValue ?? '');
								}
							}
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

where

 

entitySchemaName - the name of the entity schema whose data is displayed in the lookup window. Optional parameter. If not specified, the data source is taken from the attribute specified in itemAttributeName

 

caption - optional parameter, displayed in the window title. If caption is not specified, the caption is taken from the attribute specified in the itemAttributeName parameter. If itemAttributeName is not specified, then from the entity schema.

 

schemaName - the name of the schema that is displayed in the lookup window. Optional parameter. Default is BaseLookupPageTemplate

 

itemAttributeName - the name of the attribute from which the title is taken, the name of the entity schema and in which the result of the selection in the window will be written. Optional parameter. As a rule, this is the attribute with which the Combobox control is associated.

 

itemsAttributeName - the name of the attribute from which the data source name is taken. Optional parameter.

 

afterClosed - callback function returning the result of the selection in the window. Optional parameter.

 

filtersConfig-  describes the filter to be applied to the data. Optional parameter

 

PageLookupFeatures

 

Additionally, the user can specify additional features for the selection window.

export interface PageLookupFeatures {
    create?: {
        enabled: boolean;                         // false by default
    };
    select: {
        multiple: boolean;                        // false by default
        selectAll: boolean;                       // false by default
    };
    showDeactivatedRecords?: boolean;
}

 

The user should provide the Create option as enabled to display the New button in the selection window (only for the FreedomUI host).

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	"features": {
		"create": {
            "enabled": true;
        }
	}
});

 

The New button in this window works best only in the Freedom UI shell. In the Classic UI, new record will be created, but the selection window will close after saving it without passing the created record selected value. If you want to use this window in the Classic UI, please consider it, or don’t show this button there.

 

SelectionWindowResult  type

export class SelectionWindowResult {
    canceled: boolean; // indicates whether selection window was canceled by user
    filter: FilterMetadata; // Filter 
    async getLookupValues(options?: { pagingConfig: DataSourcePagingConfig }): Promise<LookupValue[]>; // method to get lookup values
}

where DataSourcePagingConfig is 

interface DataSourcePagingConfig {
    rowsOffset: number;
    rowCount: number;
}

example

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	"features": {
		"select": {
            "multiple": true;
        }
	},
	afterClosed: async (selectionWindowResult) => {
		const filter = selectionWindowResult.filter // getting filter
		// or 
		const lookupValues = await selectionWindowResult.getLookupValues(); // getting lookupValues
	}
});

 

Multiselection mode

 

To enable multiselection mode user should add next feature to OpenPageLookupRequest

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
            "multiple": true
        }
	}
});

So afterClosed will look like this 

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		const lookupValues = await selectionWindowResult.getLookupValues();
		// do something with lookup values
	}
});

 

Select all


To enable the ability to select all records, you should add the next features to OpenPageLookupRequest.

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
            multiple: true,
            selectAll: true
        }
	}
});

 

Canceled
 

Handling cases when the user presses the cancels Selection window

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: (selectionWindowResult) => {
		const canceled = selectionWindowResult.canceled;
		if (canceled) {
			// do some logic when user canceled selection window
		}
	}
});

 

Selecting a special set of values


getLookupValues could be called with paging config where user can specify rowsOffset and rowCount to get a specific list of values

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		const pagingConfig = {
			rowsOffset: 2,
			rowCount: 2
		}
		const lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig });
		// do something with received lookup values
	}
});

Example of iterating through lookupValues. Getting pair of 2 lookupValues with step of 2

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		let rowsOffset = 0;
        const rowCount = 2;
        const pagingConfig = { rowsOffset, rowCount };
        let lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig });
        while (lookupValues.length) {
            /*
              fn(lookupValues); // do something with received lookupValues pair
            */
            rowsOffset += 2;
            lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig: { rowsOffset, rowCount }});
        }
        if (!lookupValues.length) {
            /*
              Do some logic here on end of list - when there are no more lookupValues
            */
        }
	}
});

 

Selection state


and SelectionState is:

{
    type: 'specific';
    selected: unknown[]; // array of id's
}

 

So user can predefine selected rows, which will be pre-selected

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	...
	selectionState: {
		type: 'specific',
		selected: [
			'9d06bf9f-eb7a-4849-b83d-cbba994f185d',
			'49ba9a9e-2e28-48cb-b1bc-81b7871acb9d',
		],
	},
});

 

showDeactivatedRecords


When set to true, deactivated entries of the object are shown.

 

This is all the information that we have on the lookup page handling cases, I hope it helps.

Show all comments