Skip to main content

Input Handlers

Input is handled inline as your templates execute in an immediate mode style. There are three phases to input:

  • BeforeUpdate runs after parameters have been passed to your element for this frame but before the update hooks are invoked
  • AfterUpdate runs after the update hooks have been invoked but before any children have run
  • AfterChildren runs after all descendents have been updated

Input handlers are the same for typography, template and decorator. function cannot declare input handlers.

In template code, all input handlers have the same format of event_class:event_name => expression. The expression can be either a single line statement or a block. Inside of an event handler the $evt built in becomes available. Its type will depend on the event being fired.

template InputExample {

state int clicks;
state int focusCount;

mouse:down => clicks++;

focus:gained => {
Debug.Log($"Gained focus {focusCount} times!");

You can modify which phase the event handler fires on with the .beforeUpdate, .afterUpdate and .afterChildren modifiers.

By default, events are fired in the afterChildren phase.

decorator SomeDecorator {

key:down.beforeUpdate => Debug.Log($"{$evt.keyCode} was pressed");
key:down.afterUpdate => Debug.Log($"{$evt.keyCode} was pressed");
key:down.afterChildren => Debug.Log($"{$evt.keyCode} was pressed");


Events effectively fire for a whole hierarchy unless event.StopPropagation() is called. Once called, this event type is dead for the duration of the frame and no other element can respond to it.

A common practice in UI frameworks is have the concept of event bubbling and capture. While Evolve doesn't directly implement events in this way, because of the way the event phases are executed we can emulate this fairly well.

Using from with input events

When using a from mapping, the event signature must match the below 'Mapping Signature' table. In all cases except for drag:create the return type of the linked method is ignored and an be anything. If you use the shorthand for mapping an input handler from a companion such as mouse:down from $companion then the method name must match the name given in the 'Mapping Signature' column. If you supply the method name explicitly such as mouse:down from $companion.SomeMethod or mouse:up from someState.SomeMethod then only the signatures must match. Note that the shorthand that omits the method name is only valid for $companion

Mouse Event Types

Event NameMethod Mapping Name

Keyboard Event Types

Event NameMapping Method Name

Focus Event Types

Event NameMapping Method Name

Drag Event Types

Drag Event Types

Drag create is a special snowflake because it accepts a MouseInputEvent and expects to return an instance of DragEvent. All other drag handlers conform to the same signature requirements. If you omit a drag event type (listed as T in the table below), then these events will fire any drag event type.

Event NameMapping Method NameDescription
drag:createDragEvent OnDragCreate(MouseInputEvent))Fires when a drag could begin. Returning null will not start a drag. Returning any other subclass of DragEvent will being a drag.
drag:move<T>OnDragMove(DragEvent)Fires when a drag of type T moves across this element
drag:hover<T>OnDragHover(DragEvent)Fires when a drag of type T hovers over this element
drag:update<T>OnDragUpdate(DragEvent)Fires when a drag of type T moves or hovers over this element
drag:enter<T>OnDragEnter(DragEvent)Fires when a drag of type T enters this element
drag:exit<T>OnDragExit(DragEvent)Fires when a drag of type T exits this element
drag:drop<T>OnDragDrop(DragEvent)Fires when a drop event of type T occurs on this element
drag:cancel<T>OnDragCancel(DragEvent)Fires when a drag event of type T is canceled on this element