SAP / ui5-typescript

Tooling to enable TypeScript support in SAPUI5/OpenUI5 projects
https://sap.github.io/ui5-typescript
Apache License 2.0
200 stars 28 forks source link

Export generated type definitions from `ts-interface generator` #400

Closed marianfoo closed 1 year ago

marianfoo commented 1 year ago

I have a question if this is even possible: I use a component and the interface generator. This component is published on npmjs. Now I want to pass the generated types there so that the developers can use these types. For example the methods for attaching events or events parameter.

I tried a few things but nothing worked. This is my current status on my test branch:

Is it understandable what i'm trying to achieve? I'm fine with workarounds/hacks just to make it work experimentally. Do you need any other information? Thanks!

marianfoo commented 1 year ago

So target would be something like this, using the component in a generated Fiori Elements V4 Typescript Application.
Using ExcelUploadComponent and ExcelUploadComponent$CheckBeforeReadEvent from the ExcelUploadComponent.ts and ExcelUploadComponent.d.ts

export async function openExcelUploadDialog(this: ExtensionAPI) {
    let excelUpload = this.getRouting().getView().getController().excelUpload as ExcelUploadComponent;
    this.getRouting().getView().setBusyIndicatorDelay(0);
    this.getRouting().getView().setBusy(true);
    if (!this.getRouting().getView().getController().excelUpload) {
        excelUpload = await this.getRouting()
            .getView()
            .getController()
            .getAppComponent()
            .createComponent({
                usage: "excelUpload",
                async: true,
                componentData: {
                    context: this,
                    activateDraft: true
                }
            });
        this.getRouting().getView().getController().excelUpload = excelUpload;
        // event to check before uploaded to app
        excelUpload.attachCheckBeforeRead(function (event: ExcelUploadComponent$CheckBeforeReadEvent) {
            // example
            const sheetData = event.getParameter("sheetData");
            let errorArray = [];
            for (const [index, row] of sheetData.entries()) {
                //check for invalid price
                for (const key in row) {
                    if (key.endsWith("[price]") && row[key].rawValue > 100) {
                        const error = {
                            title: "Price too high (max 100)",
                            row: index + 2,
                            group: true,
                            rawValue: row[key].rawValue,
                            ui5type: "Error"
                        };
                        errorArray.push(error);
                    }
                }
            }
            oEvent.getSource().addArrayToMessages(errorArray);
        }, this);
    }
    excelUpload.openExcelUploadDialog();
    this.getRouting().getView().setBusy(false);
}
marianfoo commented 1 year ago

@petermuessig helped me here to solve this including finding a bug in ui5-tooling-transpile.
I used the template generator from fiori tools to generate the typescript app. I had to add ui5-cc-excelupload (name of the npm package) and "typeRoots": ["./node_modules"] to tsconfig.json so it would look like this:

"types": [ "@sapui5/ts-types-esm", "ui5-cc-excelupload" ],
"typeRoots": ["./node_modules"]

So the controller extension looks like this now using the Component and the Event Parameter:

import ExcelUploadComponent, { ExcelUploadComponent$CheckBeforeReadEventParameters } from "cc/excelUpload/v0_19_1/ExcelUploadComponent";
import ExtensionAPI from "sap/fe/core/ExtensionAPI";
import Event from "sap/ui/base/Event";
/**
 * Generated event handler.
 *
 * @param this reference to the 'this' that the event handler is bound to.
 * @param pageContext the context of the page on which the event was fired
 */
export async function openExcelUploadDialog(this: ExtensionAPI) {
    const view = this.getRouting().getView();
    const controller = view.getController()
    let excelUpload = controller.excelUpload as ExcelUploadComponent;
    view.setBusyIndicatorDelay(0);
    view.setBusy(true);
    if (!controller.excelUpload) {
        excelUpload = await this.getRouting()
            .getView()
            .getController()
            .getAppComponent()
            .createComponent({
                usage: "excelUpload",
                async: true,
                componentData: {
                    context: this,
                    activateDraft: true
                }
            });
        controller.excelUpload = excelUpload;
        // event to check before uploaded to app
        excelUpload.attachCheckBeforeRead(function (event: Event<ExcelUploadComponent$CheckBeforeReadEventParameters>) {
            // example
            const sheetData = event.getParameter("sheetData");
            let errorArray = [];
            for (const [index, row] of sheetData.entries()) {
                //check for invalid price
                for (const key in row) {
                    if (key.endsWith("[price]") && row[key].rawValue > 100) {
                        const error = {
                            title: "Price too high (max 100)",
                            row: index + 2,
                            group: true,
                            rawValue: row[key].rawValue,
                            ui5type: "Error"
                        };
                        errorArray.push(error);
                    }
                }
            }
            (event.getSource() as ExcelUploadComponent).addArrayToMessages(errorArray);
        }, this);
    }
    excelUpload.openExcelUploadDialog();
    view.setBusy(false);
}