# Infor M3 H5 Script TypeScript Template Generator

> Source: https://netray.co/tools/infor-m3-h5-script-typescript-template-generator
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: Free Tools

## Short answer

Generate a starting H5 script class that reads a field on an M3 panel, calls an MI transaction and shows the answer on the panel, on load or before Enter.

## Category

developer

## Erp

Infor M3

## Audience

- M3 developer
- H5 script developer
- M3 technical consultant

## Tool

**Kind:** template

**Output:** code

**Language:** typescript

**Fields:**

#### Script class name

**Key:** class_name

**Type:** text

**Default:** MMS001_ShowItemStatus

#### Program and panel

**Key:** panel

**Type:** text

**Default:** MMS001/E

#### Panel field to read

**Key:** field

**Type:** text

**Default:** WBITNO

#### MI program

**Key:** mi_program

**Type:** text

**Default:** MMS200MI

#### MI transaction

**Key:** mi_transaction

**Type:** text

**Default:** GetItmBasic

#### MI input field that receives the panel value

**Key:** mi_input

**Type:** text

**Default:** ITNO

#### MI output field to show

**Key:** mi_output

**Type:** text

**Default:** STAT

#### When to run

**Key:** event

**Type:** select

**Options:**

- Init
- Requesting

**Default:** Init

**Help:** Init runs when the panel loads; Requesting runs before Enter is sent.

#### Label row (Top)

**Key:** top

**Type:** number

**Default:** 2

#### Label column (Left)

**Key:** left

**Type:** number

**Default:** 60

**Blocks:**

#### {{class_name}}.ts

**Body:** // H5 script for {{panel}}: reads {{field}}, calls {{mi_program}}/{{mi_transaction}}, shows {{mi_output}}.
// Run mode: {{event}}
class {{class_name}} {
    private controller: IInstanceController;
    private log: IScriptLog;
    private unsubscribeRequesting: Function;
    private unsubscribeRequested: Function;
    private static readonly RUN_ON: string = "{{event}}";

    constructor(scriptArgs: IScriptArgs) {
        this.controller = scriptArgs.controller;
        this.log = scriptArgs.log;
    }

    public static Init(args: IScriptArgs): void {
        new {{class_name}}(args).run();
    }

    private run(): void {
        if ({{class_name}}.RUN_ON === "Requesting") {
            this.unsubscribeRequesting = this.controller.Requesting.On((e: IRequestingEventArgs) => {
                this.onRequesting(e);
            });
            this.unsubscribeRequested = this.controller.Requested.On(() => {
                this.detach();
            });
        } else {
            this.lookup();
        }
    }

    private onRequesting(e: IRequestingEventArgs): void {
        if (e.commandType === "KEY" && e.commandValue === "ENTER") {
            this.lookup();
        }
    }

    private detach(): void {
        if (this.unsubscribeRequesting) { this.unsubscribeRequesting(); }
        if (this.unsubscribeRequested) { this.unsubscribeRequested(); }
    }

    private lookup(): void {
        const value: string = this.controller.GetValue("{{field}}");
        if (!value) {
            this.log.Info("{{class_name}}: {{field}} is empty, nothing to look up");
            return;
        }
        const request = new MIRequest();
        request.program = "{{mi_program}}";
        request.transaction = "{{mi_transaction}}";
        request.record = { {{mi_input}}: value };
        request.outputFields = ["{{mi_output}}"];

        MIService.Current.executeRequest(request).then((response: IMIResponse) => {
            const item = response.item;
            const shown: string = item ? String(item["{{mi_output}}"]) : "(no record)";
            this.log.Info("{{class_name}}: " + value + " -> {{mi_output}} = " + shown);
            this.showLabel("{{mi_output}}: " + shown);
        }).catch((response: IMIResponse) => {
            this.log.Error("{{class_name}}: {{mi_program}}/{{mi_transaction}} failed: " + response.errorMessage);
            this.showLabel("Lookup failed: " + response.errorMessage);
        });
    }

    private showLabel(text: string): void {
        const label = new LabelElement();
        label.Name = "{{class_name}}_lbl";
        label.Value = text;
        label.Position = new PositionElement();
        label.Position.Top = {{top}};
        label.Position.Left = {{left}};
        label.Position.Width = 30;
        this.controller.GetContentElement().AddElement(label);
    }
}

#### Deploy and attach

**Body:** 1. Compile the TypeScript to JavaScript with the H5 Script SDK typings referenced (tsc, target as in the SDK samples).
2. Upload {{class_name}}.js in H5 Administration Tools > Scripts.
3. Open {{panel}}, then Tools > Personalize > Scripts, add script {{class_name}} and save.
4. Reload the panel and check the script log for the Info lines.

**Notes:** This is a starting point, not tested against your SDK build. Before deploying, check every name against the H5 Script SDK typings shipped with your H5 version: IScriptArgs, IInstanceController.GetValue, Requesting/Requested.On and the unsubscribe function they return, IRequestingEventArgs commandType and commandValue, MIRequest, MIService.Current.executeRequest, IMIResponse item and errorMessage, LabelElement, PositionElement and GetContentElement().AddElement. The panel field name ({{field}}) is the screen field, not the MI field: confirm it with the field help on the panel.

## Content

**Intro:** This generator writes a TypeScript H5 script class that reads a field on an M3 panel, calls one MI transaction and shows the result on the same panel. It targets the H5 Script SDK structure used with M3 13.x on-prem: a class with a static Init entry point that receives the script arguments.

**Sections:**

#### How to use it

**Body:** Name the class after the program and purpose, enter the program and panel (for example MMS001/E), the screen field to read (the default WBITNO is an example; confirm the real name with field help on your panel), the MI program and transaction, the MI input field that takes the screen value and the output field to show. Choose Init to run when the panel loads, or Requesting to run each time the user presses Enter. The label position uses the panel grid (rows and columns), so start at the default and move it if it overlaps a field.

**Bullets:**

- Keep one script per job; small scripts are easier to debug
- Use Get transactions in scripts, never Add or Upd without a confirm step
- Log with log.Info while testing and remove noisy lines afterwards

#### How the generated class is structured

**Body:** H5 calls the static Init method with the script arguments. The constructor keeps the controller (the panel instance) and the log. run() either does the lookup immediately or subscribes to the Requesting event and filters for the Enter key; it also subscribes to Requested so both handlers are removed after the request, because H5 calls Init again when the panel reloads. lookup() reads the field with the controller, builds an MIRequest with program, transaction, input record and output fields, and executes it through MIService. The promise resolves with the response item, or rejects with an error message that the script logs and shows.

#### Worked example

**Body:** On MMS001/E the script reads the item number field (confirm its screen name with field help), calls MMS200MI GetItmBasic with ITNO set to that value and asks only for STAT. If the item exists, the label shows STAT: 20 and the log records the value. If the item does not exist, GetItmBasic returns an error and the label shows the M3 message. Asking for only the output fields you need keeps the call small, which matters when the script runs on every Enter.

#### Gotchas

**Body:** Screen field names differ from MI field names: panel fields carry a prefix (for example W1, WW or WB), while the API uses plain names such as ITNO. Event handlers that are not removed fire multiple times after a few panel reloads. Calls run as the logged-in user, so MI security and the user's company and division apply. Scripts that call transactions on Requesting add latency to every Enter; keep them fast or run them on Init. Test in a non-production environment and keep the compiled file and source together in version control.

**Cta:** If you would rather let users ask M3 these questions in plain English on your own servers, we can set up a private assistant that reads the same MI transactions.

**Faq:**

#### What is the entry point of an M3 H5 script?

**Answer:** A class with a public static Init method. H5 calls Init with the script arguments, which include the controller for the current panel instance, a log and the argument string configured when the script was attached. Most scripts create an instance in Init and keep the controller and log as members.

#### How do I call an M3 API from an H5 script?

**Answer:** Build an MIRequest with program, transaction, an input record and the output fields you need, then execute it through MIService, which returns a promise. Handle the resolved response item and the rejected error message. Calls run with the logged-in user's authority, so MI security applies.

#### Where do I upload and attach an H5 script?

**Answer:** Upload the compiled JavaScript file in H5 Administration Tools under Scripts. Then open the target program and panel, go to Tools, Personalize, Scripts, and add the script by name. Reload the panel to run it. Personalizations can be set per user, role or globally depending on your rights.

#### Do I need TypeScript to write H5 scripts?

**Answer:** No, H5 runs JavaScript. TypeScript with the H5 Script SDK typings catches wrong method names and types at compile time, which is why many teams write scripts in TypeScript and deploy the compiled JavaScript. Compile with the target used in the SDK samples for your H5 version.

## Search terms

infor m3 h5 development guide, m3 h5 script, infor m3 h5 scripting, m3 h5 sdk, infor m3 h5 sdk, h5 script MIService, h5 script typescript example, m3 h5 script call mi api

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
