Reactivity

The Reactive mixin is the mechanism that keeps MATLAB properties, events, and methods in sync with their Svelte counterparts. The ic.mixin.Reactive introspects the component class at construction time, finds everything marked Description = "Reactive", and wires up the bridge subscriptions automatically. This article covers the three reactive types and how each one flows between MATLAB and the frontend.

Properties

Reactive properties are declared with SetObservable and Description = "Reactive":

properties (SetObservable, Description = "Reactive")
    Value (1,1) double = 0
    Label (1,1) string = ""
    Disabled (1,1) logical = false
end

When declared, the Reactive mixin creates a subscription for each property that listens for @prop/{name} events from the frontend. It also attaches a PostSet listener that publish changes back to the frontend. This creates a two-way sync: when MATLAB changes the property, the new value is sent to the frontend; when the frontend changes the property, the new value is sent back to MATLAB.

MATLAB to JS

When MATLAB code sets a reactive property, the PostSet listener fires. The Reactive mixin calls sendReactiveProperty(), which publishes the new value as a @prop/{Name} event. This event travels through the parent chain to the View and arrives on the JS side.

The JS Component on the frontend receives the event in camelCase (@prop/{name}) and updates the corresponding $state property from the Svelte component. Since $state is reactive, any part of the Svelte template that reads that prop re-renders automatically with the new value.

MATLAB sets a property, PostSet fires, value arrives on the JS side

JS to MATLAB

When the Svelte component writes to a property (e.g. user types into an input), the custom setter for the $state property fires and publishes @prop/{name} back to MATLAB (note that this is debounced by 50ms to prevent flooding).

On the MATLAB side, the Reactive mixin has a subscription for @prop/{Name}. It calls setValueSilently(), which disables the PostSet listener before writing the property, then re-enables it. This prevents the change from echoing back to JS.

Svelte writes a property, the 50ms debounce fires, MATLAB receives it silently

Events

Reactive events are declared with Description = "Reactive":

events (Description = "Reactive")
    Clicked
    ValueChanged
    ValueChanging
end

Events are unidirectional: they only flow from the frontend to MATLAB. They represent user interactions like clicks, drags, or text commits.

JS to MATLAB

Each reactive event is exposed to the Svelte component as a callable function prop (e.g. clicked). When the user interacts with the component, the Svelte template calls that function with a payload. This publishes @event/{name} to MATLAB, where the Reactive mixin converts it into a native notify() call that user code can listen to with addlistener.

Svelte calls the event prop, the value crosses the bridge, MATLAB fires notify()
btn = ic.Button("Label", "Click me");
frame.addChild(btn);

% This triggers @listenEvent on the frontend
l = addlistener(btn, "Clicked", @(~, e) ...
    disp("Clicked with data: " + e.Data.value));

% When l goes out of scope or is cleared,
% @unlistenEvent fires and the frontend stops forwarding

Lazy activation

The event props are not always active. When no MATLAB listener is attached, the event function is undefined, and calls from Svelte are silently ignored. This avoids sending bridge messages for events nobody is listening for.

The Reactive mixin overrides addlistener to track a reference count per event. When the first listener is attached, it publishes @listenEvent to the frontend, which creates the internal handler. When the last listener is removed (cleared or goes out of scope), it publishes @unlistenEvent, which sets the handler back to undefined.

Lazy activation: the frontend only forwards events when MATLAB is listening

Methods

Reactive methods are declared with Description = "Reactive":

methods (Description = "Reactive")
    function out = focus(this)
        out = this.publish("focus", []);
    end

    function out = getSelectedText(this)
        out = this.publish("getSelectedText", []);
    end
end

Methods are request/response calls from MATLAB to the frontend. MATLAB calls the method, which publishes the method name as an event and returns a Promise. The JS Component receives the call and executes the implementation of the method, that is bound to the Svelte component. It then publishes the result back on @resp/{uuid}.

MATLAB calls a method, JS executes it, result returns via @resp/uuid

The Svelte component provides the method implementation by assigning a function to the corresponding $state property. If not defined, the JS Component initializes each method with a default no-op that returns { success: true, data: null }.

Name conversion

MATLAB uses PascalCase (ValueChanged), JavaScript uses camelCase (valueChanged). The toCamelCase() utility handles conversion at every boundary:

MATLABJSChannel
Valuevalue@prop/value
Clickedclicked@event/clicked
ValueChangedvalueChanged@event/valueChanged
getSelectedTextgetSelectedTextgetSelectedText

The conversion happens once during setupReactivity() when subscriptions are created. After that, all matching is by the camelCase name.