External enumeration A12 2024.06

Hi there,

We’re upgrading from 2023.06 to 2024.06 and got a different behavior for external enumeration fields.

The fields configured using external resources seem not to be up to date with the state of the client.

When opening the form in the first time the enumerations are set in the selector, but in the auto-complete UI, it does not show up enumerations


When opening the form in the second time it works.

The behavior above didn’t happen in A12 2023.06 ext 6.
Are there any breaking changes in the form engine related to A12 upgrading?
Is there anyone who can help here?

Please see the implementations below:
Our sagas take the ActivityActions.setData.match(action) || initAndLoadCandidates.match(action)
Selector:

export namespace BaseExternalEnumerationSelectors {

	const log = LoggerFactory.getLogger("ExternalEnumerationSelector");

	export interface ExternalEnumerationsStore {
		externalEnumerations: ExternalEnumerationState;
	}

	export function enumerations(source: string): Selector<ReadonlyObjectMap<{ [key: string]: string | undefined }>> {
		return storeState => {
			log.trace(`Retrieving external enumerations for source ${source}`);
			if (typeof (storeState as ExternalEnumerationsStore).externalEnumerations !== "undefined") {
				const externalEnumObjs = (storeState as ExternalEnumerationsStore).externalEnumerations.values[source];
				if (typeof externalEnumObjs === "undefined") {
					return {};
				}

				let enumValues = {};

				for (const element of externalEnumObjs as IMappedEnumValue[]) {

					let labels: { [key: string]: string } = {};
					for (const label of element.label as Label[]) {
						labels = {
							...labels,
							[label.locale]: label.text
						}
					}

					enumValues = {
						...enumValues,
						[element.value]: labels
					};
				}

				return enumValues;
			} else {
				return {};
			}
		};
	}
}

Reducer:

export namespace ExternalEnumerationReducer {

	const log = LoggerFactory.getLogger("ExternalEnumerationReducer");

	export interface ExternalEnumerationState {
		readonly values: any;
	}

	export const externalEnumerations: Reducer<ExternalEnumerationState> =
		(state: ExternalEnumerationState = {values: {}}, action: Action = {type: ""}): ExternalEnumerationState => {
			if (isType(action, Q2BExternalEnumeration.setExternalEnumeration)) {
				log.trace(`Adding external enumerations for '${action.payload.source}' to store.`);
				return {
					values: {
						...state.values,
						[action.payload.source]: action.payload.values
					}
				};
			}
			return state;
		};
}

Provider

export namespace BaseExternalEnumerationProvider {

	const log = LoggerFactory.getLogger("BaseExternalEnumerationProvider");

	export function provider(state: object): IExternalEnumerationProvider {
		return source => {
			log.trace(`Providing enumerations for source ${source}`);
			const enumerations = BaseExternalEnumerationSelectors.enumerations(source)(state);
			return enumerations ? enumerations : {};
		};
	}
}

Versions:

"@com.mgmtp.a12.base/base-model-api": "28.1.1"
"@com.mgmtp.a12.client/client-core": "15.1.2"
"@com.mgmtp.a12.dataservices/dataservices-access": "37.1.2"
"@com.mgmtp.a12.devtools/devtools": "6.0.0"
"@com.mgmtp.a12.devtools/eslint-config": "0.6.0"
"@com.mgmtp.a12.devtools/prettier-config": "0.4.0"
"@com.mgmtp.a12.expression/expression-core": "1.0.3"
"@com.mgmtp.a12.formengine/formengine-core": "37.1.2"
"@com.mgmtp.a12.kernel/kernel-core-runtime-api-ts": "29.3.0"
"@com.mgmtp.a12.kernel/kernel-md-facade": "29.3.0"
"@com.mgmtp.a12.overviewengine/overviewengine-core": "37.1.2"
"@com.mgmtp.a12.relationshipengine/relationshipengine-core": "1.1.1"

Best, Nhat.

Hi,

I’m not aware of any breaking change and I don’t see the problem from the code alone. Could it be, that the autocomplete widget renders before the activity data is loaded (and setData gets dispatched)? In your logging, do you see the “Providing enumerations” message(s) before the “Adding external enumerations” message?

Hi @tim-deep-thread ,
Please see image below for the logs:

S.t was changed with a12 2024.06 but I fixed the issue by creating a redux connect to subscribe my component to the store to get the enum list updated and stored in the state, see:

from:

function createEnginesViewProvider(store: Store<object>): (componentName: string) => React.ComponentType<View> | undefined {
	const components: { [name: string]: React.ComponentType<View> | undefined } = {
		CustomFormEngine(props) {
			return <CustomRelationshipFormEngineView {...props}

			                                         externalEnumerationProvider={BaseExternalEnumerationProvider.provider(store.getState())}/>;
		},
		FormCRUD(props) {
			return <CRUDViews.FormEngineView {...props}
			                                 externalEnumerationProvider={BaseExternalEnumerationProvider.provider(store.getState())}/>;
		},
		OverviewCRUD(props) {
			return <CRUDViews.OverviewEngineView {...props} />;
		},
		CustomOverviewEngine(props) {
			return <CustomOverviewEngine {...props} />;
		},
		StaticPageComponent(props) {
			return <StaticPageComponent {...props} />;
		},
	};
	return name => {
		return components[name];
	};
}

to:

function createEnginesViewProvider(store: Store<object>): (componentName: string) => React.ComponentType<View> | undefined {
	const components: { [name: string]: React.ComponentType<View> | undefined } = {
		CustomFormEngine(props) {
			return <ConnectedExternalEnumerationFormEngineContainer {...props} />;
		},
		FormCRUD(props) {
			return <CRUDViews.FormEngineView {...props}
			                                 externalEnumerationProvider={BaseExternalEnumerationProvider.provider(store.getState())}/>;
		},
		OverviewCRUD(props) {
			return <CRUDViews.OverviewEngineView {...props} />;
		},
		CustomOverviewEngine(props) {
			return <CustomOverviewEngine {...props} />;
		},
		StaticPageComponent(props) {
			return <StaticPageComponent {...props} />;
		},
	};
	return name => {
		return components[name];
	};
}

const ConnectedExternalEnumerationFormEngineContainer: React.ComponentType<View & FormEngineViews.FormEngineProps> =
	connect<object, object, View>(
		(state) => {
			return {
				externalEnumerationProvider: BaseExternalEnumerationProvider.provider(state),
			};
		},
		() => ({}))
	(CustomRelationshipFormEngineView);

Cheers,
N.

The state inside the ExternalEnumProvider was not up to date. Subscribing to the store is the correct way of fixing it. It worked previously, because the viewProvider was called after you updated the enumerations. We don’t consider a change in rendering order / timing a breaking change / bug.

@nhat-round-cloud: Please mark this post as resolved (you can accept your own answer), so that we can stop tracking it.