This repository has been archived by the owner. It is now read-only.
Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
159 lines (115 sloc) 4.08 KB
title description layout weight
Inline Events
guide
150

Another feature Metal.js has that can be very useful is the ability to declare events inside templates, directly on the desired element. Besides being simple and intuitive, this feature allows Metal.js to handle attaching events itself, and so this can be done in the best way possible, with {sp}delegates for example, without the user having worry about that at all. These events are also automatically detached when the component is disposed.

Inline Listeners - via Function Name

You can add DOM event listeners easily through your templates, like this:

<button onClick="close" type="button" class="close">

The above code declares that whenever the x button is clicked, the {sp}close function from the component should be called.

Inline Listeners - via Function Reference

If you prefer though, you can also pass the actual function reference (instead of just its name) as an inline listener.

// src/Modal.soy

/**
 * In the "render" template, soy params that match a
 * component's function name will be that function
 * (automatically bound to the component instance).
 */
&#123;template .render&#125;
  {@param close: any}

  // ...
  <button onClick="{$close}" type="button" class="close">
  // ...
&#123;/template}
// src/Modal.js

<button onClick={this.close.bind(this)} type="button" class="close">

That will work exactly the same way as the previous example.

Inline Listeners - Nested Components

When using nested components it's also possible to inline events by using the events property:

// src/Modal.soy

{call Button.render}
  {param events: ['click': ['selector': 'button', 'fn': 'close']] /}
  {param label: 'Ok' /}
{/call}
// src/Modal.js

var events = {click: {
  selector: 'button',
  fn: 'close'
}};

<Button events={events} label="Ok" />

This will cause the close function from the sub component to be called whenever a click event triggers for the elements that match the given selector.

In case you want to listen to the event with a function from the parent component, just pass the function reference instead of a string, like this:

// src/Modal.soy

{call Button.render}
  {param events: ['click': ['selector': 'button', 'fn': $close]] /}
  {param label: 'Ok' /}
{/call}
// src/Modal.js

var events = {click: {
  selector: 'button',
  fn: this.close.bind(this)
}};

<Button events={events} label="Ok" />

Besides DOM events, you can also listen to custom events from the sub component in this same way:

// src/Modal.soy

{call Button.render}
  {param events: ['labelChanged': $handleLabelChanged] /}
  {param label: 'Ok' /}
{/call}
// src/Modal.js

var events = {labelChanged: this.handleLabelChanged.bind(this)};

<Button events={events} label="Ok" />

Inline Listeners - Alternative Usage

Besides the on[EventName] format you can also use data-on[eventname] for adding inline listeners. For example:

<button data-onclick="close" type="button" class="close">

Note that this format is supported mainly to enable doing {sp}progressive enhancement, when running Soy templates via Java for example. When templates using the {sp}on[EventName] format run in Java they will output elements with these as actual attributes, which can cause errors in the browser. In JavaScript these are used as element properties instead, so this problem doesn't occur.

So feel free to use the format you like best, or that better fits your needs.