Event Handling

Listening to the events

To attach the event handler to an event use the event binding syntax:

(eventName)="statement"

For example:

class EventHandling extends BaseComponent
{
    public int $count = 0;
}
<button (click)="$count = $count + 1">Add 1</button>
<span>Count: <b>$count</b></span>

The result:

Count: 0

You can find the list of all available events at Event reference.

Component's method as an event handler

You can use component's method as an event handler:

class EventHandling extends BaseComponent
{
    public string $greetingMessage = '';

    function greet()
    {
        $this->greetingMessage = 'Hello Viewi!';
    }
}
<button (click)="greet">Greet</button>
<b>$greetingMessage</b>

The result:

Passing arguments

You can also pass arguments into the method:

class EventHandling extends BaseComponent
{
    public string $greetingMessage = '';

    function greetByName($name)
    {
        $this->greetingMessage = "Hello $name!";
    }
<button (click)="greetByName('Viewi')">Greet Viewi</button>
<button (click)="greetByName('Diana')">Greet Diana</button>
<b>$greetingMessage</b>

The result:

Event object

Sometimes you also need to access the original DOM event in your statement. For that purpose use $event variable or argument.

<form (submit)="handleSubmit($event)">
    <button>Send</button>
</form>

Or

<form (submit)="handleSubmit">
    <button>Send</button>
</form>

And now you can access it in your handleSubmit method:

use Viewi\Components\DOM\DomEvent;

class EventHandling extends BaseComponent
{
    public function handleSubmit(DOMEvent $event)
    {
        $event->preventDefault();
    }
}

Please note: if you already have in your component property $event, then you will have to use {$_component->event} in order to use the template. $event is a magic variable that contains reference to the DOM event.

Keyboard events

DomEvent has the standard keyboard fields:

  • key - the key the user pressed: 'Enter', 'Escape', 'ArrowDown', ' ' for the space bar.
  • code - the physical key on the keyboard: 'KeyA', 'Digit1', 'Space'. It does not change with the keyboard layout.
  • ctrlKey, shiftKey, altKey, metaKey - true while that key is held down.
  • repeat - true when the event comes from a key being held down.

keyCode is still there, but browsers have deprecated it. Use key instead.

use Viewi\Components\DOM\DomEvent;

class KeyEventExample extends BaseComponent
{
    public string $pressed = '';

    function onKey(DomEvent $event)
    {
        $combo = '';
        if ($event->ctrlKey) {
            $combo .= 'Ctrl + ';
        }
        if ($event->altKey) {
            $combo .= 'Alt + ';
        }
        if ($event->shiftKey) {
            $combo .= 'Shift + ';
        }
        if ($event->metaKey) {
            $combo .= 'Meta + ';
        }
        $key = $event->key === ' ' ? 'Space' : $event->key;
        $this->pressed = $combo . $key . ' (' . $event->code . ')';
    }
}
<input (keydown)="onKey" placeholder="Press any key" />
<div>Pressed: <b>$pressed</b></div>

The result:

Pressed:

For drag and drop events, $event->dataTransfer gives you the DataTransfer object. Firefox does not start a drag unless dragstart calls setData() on it.

Event modifiers

Add modifiers to the event name, separated by dots, to filter events or change how they are handled.

<input (keyup.enter)="add" (keyup.esc)="$draft = ''" />
<form (submit.prevent)="save">...</form>
<textarea (keydown.ctrl.enter)="send"></textarea>

Here is a list you can add items to. Press Enter to add an item, or Escape to clear the input:

class EventModifiersExample extends BaseComponent
{
    public string $draft = '';
    public array $items = [];

    function add()
    {
        $text = trim($this->draft);
        if ($text === '') {
            return;
        }
        $this->items = [...$this->items, $text];
        $this->draft = '';
    }
}
<input model="$draft" (keyup.enter)="add" (keyup.esc)="$draft = ''" placeholder="Type, then press Enter" />
<ul>
    <li foreach="$items as $item">$item</li>
</ul>

The result:

Key modifiers

The handler runs only for the listed key. It matches on event.key.

Modifier Key
enter Enter
esc, escape Escape
space Space bar
tab Tab
up, down, left, right Arrow keys
arrowup, arrowdown, arrowleft, arrowright Arrow keys
home, end, pageup, pagedown Home, End, Page Up, Page Down
delete Delete or Backspace
backspace Backspace

If you list two keys, either one triggers the handler: (keydown.up.down) runs for both arrows.

System modifiers

ctrl, shift, alt and meta make the handler run only while that key is held down. (keydown.ctrl.enter) runs for Ctrl + Enter.

Add exact to reject any other held keys: (keydown.ctrl.enter.exact) does not run for Ctrl + Shift + Enter.

Behaviour modifiers

Modifier Effect
prevent Calls $event->preventDefault() before the handler
stop Calls $event->stopPropagation() before the handler
self Runs the handler only when the event started on this element, not on a child
exact See system modifiers above

prevent and stop apply only when the event passes the key and system checks. (keydown.enter.prevent) blocks Enter and lets every other key through.

Listener options

once, passive and capture are passed to addEventListener as listener options.

<div (scroll.passive)="onScroll">...</div>
<button (click.once)="start">Start</button>

Modifier names are case-insensitive. An unknown modifier fails the build with the list of valid ones, so a typo like (keyup.entr) is caught when you build, not left as a handler that never runs.

Dynamic event

Well, if you really do not know what event it will be, you can use a dynamic syntax:

$myEventName="expression"

Where $myEventName should contain a valid event attribute name, like this:

public string $myEventName = '(click)';

Whenever you decide to change event name, the application will reattach events accordingly. You are allowed to change it to regular attribute name, that is also ok and application will remove the event and set attribute accordingly.