Wait for dependent data to be loaded in another JSONModel

When creating complex Freestyle SAPUI5 Apps its a good practice to organize the code in the project.
Through extending the sap.ui.model.json.JSONModel you have a clean way to organize specific code that is responsible for managing specific object data. For example, user data that needs to be read once can be outsourced to a user model. The data can then be read directly once in the Component.js.
Now… what if we need to send a request in the object page in the method _onObjectMatched that requires data from the user model as a parameter? How can we wait for the data to be loaded in the user model?
Guess what – This code snippet shows a possible solution using the Promise object.

User.ts

import ODataModel from "sap/ui/model/odata/v2/ODataModel";
import Component from "sap/ui/core/UIComponent";
import JSONModel from "sap/ui/model/json/JSONModel";

export default class User extends JSONModel {
    private serviceModel: ODataModel
    public userDataLoaded: Promise<void>
    private resolveUserDataLoaded: Function

    public constructor(component: Component) {
        super({
            busy: true,
            data: {
                Pernr: undefined
            }
        });
        this.serviceModel = <ODataModel>component.getModel();
        this.userDataLoaded = new Promise((resolve) => { this.resolveUserDataLoaded = resolve });
    }
    public async readData(key: string) {

        this.setProperty("/busy", true);
        try {
            await this.serviceModel.metadataLoaded();
            let readResponse = await this._read(key);
            this.setProperty("/data", readResponse);
            this.resolveUserDataLoaded();
        } catch (error) {
            throw error;
        } finally {            
            this.setProperty("/busy", false);
        }

    }
    private _read(key: string): Promise<void> {
        const serviceModel = this.serviceModel;
        return new Promise((resolve, reject) => {
            const path = serviceModel.createKey("/UserSet", {
                Pernr: key
            });

            const parameters = {
                success: resolve,
                error: reject
            };

            serviceModel.read(path, parameters);
        })
    }
}

models.ts

import Component from "../Component";
import User from "./User";

export function createUserModel(component: Component): User {
    const model = new User(component);
    model.setDefaultBindingMode("OneWay");
    return model;
}

Component.ts

import { createUserModel } from "./model/models";
import User from "./model/User";
        //set the user model
        this.setModel(createUserModel(this), "user");
        (<User>this.getModel("user"))?.readData("99999999");

Object.controller.ts

    private async onObjectMatched(evt: Route$PatternMatchedEvent): Promise<void> {
        const parameter = (<any>evt.getParameter("arguments"));

        //wait for user data being loaded
        //this.viewModel.setProperty("/busy", true);
        await (<User>this.getModel("user"))?.userDataLoaded;
        //this.viewModel.setProperty("/busy", false);

        //TODO: read data with information from the userModel
    }

💡 For more tips on how to organize your code check out the following blog post: How to organize your code in your SAPUI5 project

Leave a Reply

Your email address will not be published. Required fields are marked *