ExternalEnumProvider with fetching data from the backend

Peace out,

i want to show document model ids as enum in the UI. Thanks to @malcolm-silver-ice i got a hint with:

I didn’t see any possibility to retrieve these model ids from the state, but this might be due to my lack of experience. I believe I need to obtain these IDs from the backend. Unfortunately, every fetch operation is asynchronous, while the IExternalEnumerationProvider returns a direct value. I have struggled to connect the asynchronous fetch with the synchronous provider, except by implementing a (potentially) race condition with the following code. The fetch request is performed in the constructor.

export function createExternalEnumerationProvider(): IExternalEnumerationProvider {
    const documentModelIdExternalEnumProvider = new DocumentModelIdExternalEnumProvider();

    return (source: string) => {
        switch (source) {
            case "documentModelIds": {
                return documentModelIdExternalEnumProvider.getModelIdAsExternalEnum();
            }
            default:
                throw new Error("unknown external enumeration source: " + source);
        }
    };
}
export class DocumentModelIdExternalEnumProvider {
    private data: Map<string, { [key: string]: string }> = new Map();

    constructor() {
        this.getDocumentModelIds(); // Immediately initiate the fetch request during construction
    }

    private async getDocumentModelIds() {
        await importRequest().then((modelMap) => {
            // Add all models to a list
            modelMap.documentModels.map((value) =>
                this.data.set(value.modelId, { value: value.modelId, de: value.modelId })
            );
        });
    }

    public getModelIdAsExternalEnum(): ReadonlyObjectMap<{ [key: string]: string }> {
        const obj: { [key: string]: { [key: string]: string } } = {};
        for (const [key, value] of this.data) {
            obj[key] = value;
        }

        return obj as ReadonlyObjectMap<{ [key: string]: string }>;
    }
}

My question is if anyone has a better idea of implementing an asynchronous fetching request and using the result as ExternalEnumProvider

Best regards,
Tjorben

Hi @tjorben-atomic-moss,

My question is if anyone has a better idea of implementing an asynchronous fetching request and using the result as ExternalEnumProvider

the trick in here is to move the request into a new custom data provider (or your existing custom data provider for current activity). By implementing a custom dataReducer afterwards you can create a custom dataHolder for your activity that will hold your id response.

To have access to the dataHolder from ExternalEnumProvider you need to be in a stateful function (e.g. form engine implementation in your view provider) and handover the necessary slice as argument by creating your own factory function for ExternalEnumProvider. Or as alternative have other kind of access to your global state object and then use it directly in the ExternalEnumProvider.

The alternative could be a solution if you need to pass that ExternalEnumProvider also to the createEngineMiddlewares on ApplicationFactories.createApplicationSetup. But from my experience it is not explicitly necessary to register stateful external enum providers in the middelwares instead i only register empty or not stateful providers there and until now i never faced an issue with that (i am open for objections here :slight_smile: )

Cheers
Markus

Hey Markus,

this sound like a complicate solution, but thank you for this answer and at least there is a solution. Are there other solutions from other projects or any plans in A12 for making it easy to implement ?