Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript Feedback (JSONModel && Promisification) #6

Open
timostark opened this issue Apr 11, 2021 · 2 comments
Open

Typescript Feedback (JSONModel && Promisification) #6

timostark opened this issue Apr 11, 2021 · 2 comments

Comments

@timostark
Copy link

timostark commented Apr 11, 2021

Hi All,

First thank you very much for the typescript branch. I am really super excited about the progress made here. I think the overall developments in this direction will be a giantic step for the UI5 development generally. After developing a year with typescript I really don't want to go back - It is fantastic that my day-to-day framework now makes that step too..

Regarding typescript the most "urgent" open point was mentioned in PR #5.
There are however two more open points, which I'd like to address, which might be a big help for application developers. Both can be easily implemented by customers, so are therefore no blockers at all, but imo would be great inside the core product / framework.
I am not sure if that is the right place (probably more the typescript or the openui5 repo?), but still I want to give you short feedback also regarding the sample, as maybe (if this here should be a best practice typescript application) you might add sth. of the examples below inside your code.

Open up JSONModel

Typescript and JSON-Model is a small "no-no" when using the "normal API". Using setProperty("long/long/1/path/without/typing", some_unknown_value) inside typescript is very sad.
In out project we have build a sub-class of the JSON Model, which:

  1. Publishes JSONModel.oData with a fixed type (template based)
  2. Allows full read-access on the type. Writing is only allowed using functions
  3. Automatically triggers a JSONModel.checkUpdate after a write function is called ("easy workaround" vs. doing deep change detection using proxies, or getter / setters, which are reducing the performance.)

For that however both "oData" && checkUpdate should be opened and made public (we are working with "any" atm, to workaround that restriction).

Example-Code: State

export class DetailControllerState {
    busy: boolean;
    public setBusy(bBusy: boolean) {
        this.busy = bBusy;
    }
}
export type DetailControllerStateRO = { +readonly [P in keyof DetailControllerState]: DetailControllerState[P] };

and Usage inside a controller..
grafik

Using that "State" approach you can mostly avoid using formatter by using "getters" instead (ofc not "perfect", as the change detection is not working here, but still nice). Example of a state method:

    get getAmountOfData(): string {
        return this.data.filter((e) => e.type=== ENUM_DATA.MY_TYPE && e.change_indicator !== "D").length.toString();
    } 

JSONModel:

export default class GenericJSONModel<T> extends JSONModel {
    public _setData(oData: T, bMerge?: boolean): void {
        this.setData(oData, bMerge);
        this._observeFunctions();
    }

    private _observeFunctions() {
        Object.getOwnPropertyNames(Object.getPrototypeOf(this.oData)).forEach((sAttr) => {
            const sVal = allData[sAttr];
            if ( typeof sVal === "function" ) {
                const funcBefore: Function = sVal;
                const funcApply = this._checkUpdate.bind(this);
                allData[sAttr] = function(...args: any[]) {
                    const ret = funcBefore.apply(this,args);
                    funcApply();
                    return ret;
                };
            }
        });
    }
}

Promisification

Using transpiler / babel we can finally use await/async - but the scope of it is somewhat limited without the use of promise based APIs. UI5 still has a lot of places where callback based APIs are published. As ofc breaking changes are not really possible, i'd suggest the creation of some reusable classes build on top of the existing APIs.
I want to give you two short examples of our current project, where we have build promisified versions of the ODataModel handler and the MessageBox method.

  1. MessageBox Handling example, asking the user if he wants to leave the current page without saving
    protected async _confirmNavBack() {
        if(!this._isDirty()) { return true; }
        const answer = await AsyncMessageBoxDef.confirm(this.getText("confirmCancelMsg"), {
            title: this.getText("confirmCancelTitle"),
        });
        return answer === Action.OK;
    }

    protected async _onNavBack() {
        const allowNavBack = await this._confirmNavBack();
        if ( allowNavBack === false ) { return; }
        this.getRouter().navTo("Master");
    }
  1. ODataModel handler read call, including static typings (using templates)
        try {
            const headData = await this._oModel.read(sNormalizedPath);
           //access all elements, headData is statically typed using DTOs etc..
            if (headData.status === "2") {
                return;
            }
        } catch (e) {
            return;
        }

Regards,
Timo

@timostark timostark changed the title Typescript Feedback Typescript Feedback (JSONModel && Promisification) Apr 11, 2021
@akudev
Copy link
Contributor

akudev commented Apr 13, 2021

Hi Timo, thanks a lot for your detailed feedback! We're definitely looking into it.
Promisification of the V2 ODataModel has been rejected recently (SAP/openui5#3058), but I think it doesn't hurt to have a second look, considering that new APIs could be added etc.

@timostark
Copy link
Author

timostark commented Apr 14, 2021

Hi @akudev ,

Thanks for the response. FYI: I've uploaded examples for all suggestions using Northwind Service inside https://github.com/timostark/ui5-typescript-sample.
(and I am still super happy to finally develop with typescript in UI5).

The statically typed JSON model is really super nice to be used honestly :-) Change-detection is now done using decorators.
grafik

Do you plan to provide decorators from your side? An example would be a decorator for UI5-Elements.
grafik

Greets,
Timo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants