A Widget represents a server side object that sends one or more responses to the client. The client can then interpret these responses to see what to render, or how to respond.

Most custom object types result in a single response being sent to the client, often with other exported objects, but some will have streamed responses, and allow the client to send follow-up requests of its own. This class's API is backwards compatible, but as such does not offer a way to tell the difference between a streaming or non-streaming object type, the client code that handles the payloads is expected to know what to expect. See WidgetMessageDetails for more information.

When the promise that returns this object resolves, it will have the first response assigned to its fields. Later responses from the server will be emitted as "message" events. When the connection with the server ends, the "close" event will be emitted. In this way, the connection will behave roughly in the same way as a WebSocket - either side can close, and after close no more messages will be processed. There can be some latency in closing locally while remote messages are still pending - it is up to implementations of plugins to handle this case.

Also like WebSockets, the plugin API doesn't define how to serialize messages, and just handles any binary payloads. What it does handle however, is allowing those messages to include references to server-side objects with those payloads. Those server side objects might be tables or other built-in types in the Deephaven JS API, or could be objects usable through their own plugins. They also might have no plugin at all, allowing the client to hold a reference to them and pass them back to the server, either to the current plugin instance, or through another API. The `Widget` type does not specify how those objects should be used or their lifecycle, but leaves that entirely to the plugin. Messages will arrive in the order they were sent.

This can suggest several patterns for how plugins operate:

  • The plugin merely exists to transport some other object to the client. This can be useful for objects which can easily be translated to some other type (like a Table) when the user clicks on it. An example of this is `pandas.DataFrame` will result in a widget that only contains a static Table. Presently, the widget is immediately closed, and only the Table is provided to the JS API consumer.
  • The plugin provides references to Tables and other objects, and those objects can live longer than the object which provided them. One concrete example of this could have been PartitionedTable when fetching constituent tables, but it was implemented before bidirectional plugins were implemented. Another example of this is plugins that serve as a "factory", giving the user access to table manipulation/creation methods not supported by gRPC or the JS API.
  • The plugin provides reference to Tables and other objects that only make sense within the context of the widget instance, so when the widget goes away, those objects should be released as well. This is also an example of PartitionedTable, as the partitioned table tracks creation of new keys through an internal table instance.

Handling server objects in messages also has more than one potential pattern that can be used:

  • One object per message - the message clearly is about that object, no other details required.
  • Objects indexed within their message - as each message comes with a list of objects, those objects can be referenced within the payload by index. This is roughly how Figure behaves, where the figure descriptor schema includes an index for each created series, describing which table should be used, which columns should be mapped to each axis.
  • Objects indexed since widget creation - each message would append its objects to a list created when the widget was first made, and any new exports that arrive in a new message would be appended to that list. Then, subsequent messages can reference objects already sent. This imposes a limitation where the client cannot release any exports without the server somehow signaling that it will never reference that export again.

Hierarchy

  • Widget

Implements

Constructors

Properties

EVENT_CLOSE: string
EVENT_MESSAGE: string

Accessors

  • get exportedObjects(): WidgetExportedObject[]
  • Returns WidgetExportedObject[]

    the exported objects sent in the initial message from the server. The client is responsible for closing them when finished using them.

  • get type(): string
  • Returns string

    the type of this widget

Methods

  • Listen for events on this object.

    Type Parameters

    • T

      the type of the data that the event will provide

    Parameters

    • name: string

      the name of the event to listen for

    • callback: ((e) => void)

      a function to call when the event occurs

        • (e): void
        • Parameters

          • e: CustomEvent<T>

          Returns void

    Returns (() => void)

    Returns a cleanup function.

      • (): void
      • Returns void

  • Ends the client connection to the server.

    Returns void

  • Type Parameters

    • T

    Parameters

    • eventName: string
    • Optional timeoutInMillis: number

    Returns Promise<CustomEvent<T>>

  • Removes an event listener added to this table.

    Type Parameters

    • T

    Parameters

    • name: string
    • callback: ((e) => void)
        • (e): void
        • Parameters

          • e: CustomEvent<T>

          Returns void

    Returns boolean

  • Sends a string/bytes payload to the server, along with references to objects that exist on the server.

    Parameters

    Returns void