JavaScript to Typesript Code Communication

Hello, how can I trigger methods from my TypeScript classes from the index page JavaScript, similar to Messaging done between JavaScript and the Unity player?

Tomislav, here’s the plan for “JavaScript to TypeScript Code Communication” in Needle Engine:

Pseudocode Plan

  1. Expose TypeScript methods (usually in Needle Engine Behaviour classes) to JS/global scope.
  2. On the index or surrounding JavaScript, call these exposed methods using the stored reference.
  3. Use events or direct function calls for communication.

Approach

  • Attach your Typescript Behaviour to a GameObject.
  • Store a reference to it on window or another accessible JS object.
  • Access and call its public methods from external JavaScript.

Example Implementation

// TypeScript: my-behaviour.ts
import { Behaviour } from "@needle-tools/engine";

export class MyBehaviour extends Behaviour {
    public sayHello(name: string) {
        console.log(`Hello, ${name}!`);
    }

    // Expose to JS on init
    awake() {
        // Make this instance accessible globally e.g. via window
        (window as any).myNeedleBehaviour = this;
    }
}
// index.js or another JS file outside Needle Engine
// Wait until your scene and behaviours are loaded!
window.addEventListener("load", () => {
    // Example usage
    if(window.myNeedleBehaviour) {
        window.myNeedleBehaviour.sayHello("Tomislav");
    }
});

Tips:

  • Ensure behaviour is loaded before calling (may require waiting for awake or a custom event).
  • For more complex communication, consider dispatching custom events or using an event bus.
  • Refer to the Needle Engine API for behaviour lifecycle.

Suggestions for Next Steps:

  • Share if you’re embedding as an iframe or in the same page.
  • Specify if you need 2-way communication (JavaScript ⇄ TypeScript).
  • Are you using plain JS or a framework (React, Vue, etc.)?

If you have more details on your setup or a specific use case, please provide them for tailored advice!

4 replies left
thread_yIvaijeBRAQLihr25kSeuxg4
Reply to this post directly if you need further help (bottom right button)

I am embedding on the same page
I need one-way communication JavaScript > TypeScript
using Vite

Tried code above and it didn’t work, nothing happend.

Great, Tomislav! Here’s a detailed guide for JavaScript > TypeScript (Needle Engine) one-way communication, embedding on the same page using Vite:

Pseudocode Plan

  1. Create a TypeScript Behaviour.
  2. In awake, expose its methods (by attaching its instance to window or a global object).
  3. In your Vite JS code, call methods on that Behaviour once Needle Engine and your component are loaded.

Implementation

// src/MyBehaviour.ts
import { Behaviour } from "@needle-tools/engine";

export class MyBehaviour extends Behaviour {
    myMethod(msg: string) {
        console.log("Received from JS:", msg);
    }

    awake() {
        // Expose reference globally
        (window as any).myBehaviourInstance = this;
    }
}
// src/main.js (your Vite JS entry point, outside Needle Engine)
window.addEventListener("load", () => {
  // Wait a bit to ensure Needle scene has loaded and awake() ran
  setTimeout(() => {
    if (window.myBehaviourInstance) {
      window.myBehaviourInstance.myMethod("Hello from JS via Vite!");
    } else {
      console.warn("Needle Behaviour not ready yet.");
    }
  }, 1000);
});

Tips:

  • You can dispatch a custom event from Needle once ready (for more robustness).
  • Only public methods are accessible.
  • Use Typescript’s typing features for safety in your code.

Resources:

Next Steps:

  • Try this setup, adjust the delay as needed.
  • If you need examples for robust event-driven readiness, ask!

To help further, please specify if you have multiple Behaviours or other loading requirements.

4 replies left
thread_yIvaijeBRAQLihr25kSeuxg4
Reply to this post directly if you need further help (bottom right button)

Hi, i’ve created an example here: Needle-engine - Vite Template (forked) - StackBlitz

The important bits are in index.html:


  <script type="module">
    // you can register functions individually to the 'window' or just declare them individually on global scope
    window['my_frontend'] = {
      helloWorld: (name) => {
        console.warn('HELLO WORLD ' + name);
      },
    };
    window.helloWorld2 = function () {
      console.warn('Hello world 2');
    };
    window.myAddFunction = function (num1, num2) {
      return num1 + num2;
    };
  </script>

and then you can call them e.g. from main.ts by waiting for the domcontentloaded event

// DOMContentLoaded is called by the browser when your HTML has finished loading (which contains the global functions, so we need to wait for them to be available)
document.addEventListener('DOMContentLoaded', () => {
  const result = window['myAddFunction'](1, 2);
  console.warn('1 + 2 equals ' + result);
});

OR you can call them from a component

import { Behaviour, Component, showBalloonMessage } from '@needle-tools/engine';

export class MyComponent extends Component {
  start() {
    showBalloonMessage('Open the browser console to see the function logs');
    // call the hello world function declared in global scope
    window['helloWorld2']();
    const frontend = window['my_frontend'];
    frontend.helloWorld('Test');
  }
}

Thanks