API · Custom tags

Mounting

riot.mount(customTagSelector, [opts])

customTagSelector selects elements from the page and mounts them with a custom tag. The selected elements’ name must match the custom tag name.

opts optional object is passed for the tags to consume. This can be anything, ranging from a simple object to a full application API. Or it can be a Flux- store. Really depends on how you want to structure your client-side applications. Read more about modular Riot applications. Also note that attributes you set on your tags as options will take precedence over ones specified with same names via opts argument.

// selects and mounts all <pricing> tags on the page
var tags = riot.mount('pricing')

// mount all custom tags with a class name .customer
var tags = riot.mount('.customer')

// mount <account> tag and pass an API object as options
var tags = riot.mount('account', api)

@returns: an array of the mounted tag instances

Note: users of In-browser compilation will need to wrap calls to riot.mount in riot.compile in order to get returned tag instances. Without this, calls to riot.mount will return undefined.

<script>
riot.compile(function() {
  // here tags are compiled and riot.mount works synchronously
  var tags = riot.mount('*')
})
</script>

riot.mount(‘*’, [opts])

A special Riot specific selector “*” can be used to mount all custom tags on the page:

riot.mount('*')

@returns: an array of the mounted tag instances

riot.mount(selector, tagName, [opts])

Where

// mounts custom tag "my-tag" to div#main and pass api as options
var tags = riot.mount('div#main', 'my-tag', api)

@returns: an array of the mounted tag instances

riot.mount(domNode, tagName, [opts])

Mount a custom tag named tagName on a given domNode passing optional data with opts. For example:

// mounts "users" tag to #slide node and pass api as options
riot.mount(document.getElementById('slide'), 'users', api)

@returns: an array of the mounted tag instances

Rendering

riot.render(tagName, [opts])

Rendering a tag to html.
Only available on server-side. For example:

// render "my-tag" to html
var mytag = require('my-tag')
riot.render(mytag, { foo: 'bar' })

@returns: tags render as html

riot.renderAsync(tagName, [opts])

>= v2.6.3

Rendering asynchronously a tag to html.
Only available on server-side.
This method returns a promise that will be resolved only when a “ready” event will be triggered by your tags during the mounting process. For example:

On the server:

riot.renderAsync(tagName, opts)
  .then(function(html) {
    // do something with your html
  })
  .catch(function(e) {
    // it took too much time!
  })

In your tag:

<async-rendering>
  <p>{ message }</p>

  this.message = 'hi'

  setTimeout(function() {
    // triggering the "ready" event will resolve the promise
    this.trigger('ready')
  }.bind(this), 500)

</async-rendering>

It’s important to notice that if the “ready” event will not be triggered, the promise will be rejected after 1 second. You can configure the internal riot promises timeout via riot.settings.asyncRenderTimeout (default 1000ms)

@returns: Promise

Tag instance

Following properties are set for each tag instance:

You can use these references in both the HTML and JavaScript code. For example:

<my-tag>
  <h3>{ opts.title }</h3>

  var title = opts.title
</my-tag>

You can freely set any data to the instance (aka “context”) and they are available in the HTML expressions. For example:

<my-tag>
  <h3>{ title }</h3>

  this.title = opts.title
</my-tag>

Note: if you have some globals, you can also use these references in both the HTML and JavaScript code:

window.someGlobalVariable = 'Hello!'
<my-tag>
  <h3>{ someGlobalVariable }</h3>

  var message = someGlobalVariable
</my-tag>

Updating

this.update()

Updates all the expressions on the current tag instance as well as on all the children. This method is automatically called every time an event handler is called when user interacts with the application.

Other than that riot does not update the UI automatically so you need to call this method manually. This typically happens after some non-UI related event: after setTimeout, AJAX call or on some server event. For example:

<my-tag>

  <input name="username" onblur={ validate }>
  <span class="tooltip" show={ error }>{ error }</span>

  var self = this

  validate() {
    $.get('/validate/username/' + this.username.value)
      .fail(function(error_message) {
        self.error = error_message
        self.update()
      })
  }
</my-tag>

On above example the error message is displayed on the UI after the update() method has been called. We assign this variable to self since inside the AJAX callback this variable points to the response object and not to the tag instance.

this.update(data)

Set values of the current instance and update the expressions. This is same as this.update() but allows you to set context data at the same time. So instead of this:

self.error = error_message
self.update()

you can do this:

self.update({ error: error_message })

which is shorter and cleaner.

riot.update()

Updates all the mounted tags and their expressions on the page.

@returns: an array of tag instances that are mounted on the page.

Unmounting

this.unmount(keepTheParent)

Detaches the tag and its children from the page. An “unmount” event is fired. If you want to unmount a tag without removing the parent tag you need to pass true to the unmount method

Remove the tag from the DOM:

mytag.unmount()

Remove the tag children and keep only the parent tag:

mytag.unmount(true)

Nested tags

You have access to nested tag instances via tags variable:

<my-tag>

  <child></child>

  // access to child tag
  var child = this.tags.child

</my-tag>

If more than one of the same child tag is used, it is accessed as an array this.tags.child[n]

You can also use the name attribute to give another name for the nested tag.

<my-tag>

  <child name="my_nested_tag"></child>

  // access to child tag
  var child = this.tags.my_nested_tag

</my-tag>

The child tags are initialized after the parent tag so the methods and properties are available on the “mount” event.

<my-tag>

  <child name="my_nested_tag"></child>

  // access to child tag methods
  this.on('mount', function() {
    this.tags.my_nested_tag.someMethod()
  })

</my-tag>

Yielding nested HTML

The <yield> tag is a special riot core feature that allows you to inject and compile the content of any custom tag inside its template in runtime This technique allows you to extend your tags templates with html contents rendered eventually from the server

For example using the following riot tag my-post

<my-post>
  <h1>{ opts.title }</h1>
  <yield/>
  this.id = 666
</my-post>

anytime you will include the <my-post> tag in your app

<my-post title="What a great title">
  <p id="my-content-{ id }">My beautiful post is just awesome</p>
</my-post>

once mounted riot.mount('my-post') it will be rendered in this way:

<my-post>
  <h1>What a great title</h1>
  <p id="my-content-666">My beautiful post is just awesome</p>
</my-post>

Multi-Transclusion

>=2.3.12

The <yield> tag also provides a slot mechanism that allows you to inject html contents on specific slots in the template

For example using the following riot tag my-other-post

<my-other-post>
  <article>
    <h1>{ opts.title }</h1>
    <h2><yield from="summary"/></h2>
    <div>
      <yield from="content"/>
    </div>
  </article>
</my-other-post>

anytime you will include the <my-other-post> tag in your app

<my-other-post title="What a great title">
  <yield to="summary">
    My beautiful post is just awesome
  </yield>
  <yield to="content">
    <p>And the next paragraph describes just how awesome it is</p>
    <p>Very</p>
  </yield>
</my-other-post>

once mounted riot.mount('my-other-post') it will be rendered in this way:

<my-other-post>
  <article>
    <h1>What a great title</h1>
    <h2>My beautiful post is just awesome</h2>
    <div>
      <p>And the next paragraph describes just how awesome it is</p>
      <p>Very</p>
    </div>
  </article>
</my-other-post>

Yield and loops

The <yield> tag could be used also in a loop or in a child tag but you should be aware that it will be always parsed and compiled using the child data

The following blog.tag riot component

<blog>
  <h1>{ title }</h1>
  <my-post each={ posts }>
    <a href={ this.parent.backToHome }>Back to home</a>
    <div onclick={ this.parent.deleteAllPosts }>Delete all the posts</div>
  </my-post>

  this.backToHome = '/homepage'
  this.title = 'my blog title'

  this.posts = [
    { title: "post 1", description: 'my post description' },
    { title: "post 2", description: 'my post description' }
  ]

  // the bind is needed in this case to keep the parent context
  // also in the child tags
  deleteAllPosts() {
    this.posts = []

    // we need to trigger manually the update function
    // because this function gets triggered from a child tag
    // and it does not bubble up automatically
    this.update()
  }.bind(this)

</blog>

<my-post>
  <h2>{ title }</h2>
  <p>{ description }</p>
  <yield/>
</my-post>

will be compiled in this way:

<blog>
  <h1>my blog title</h1>
  <my-post>
    <h2>post 1</h2>
    <p>my post description</p>
    <a href="/homepage">Back to home</a>
    <div>Delete all the posts</div>
  </my-post>
  <my-post>
    <h2>post 2</h2>
    <p>my post description</p>
    <a href="/homepage">Back to home</a>
    <div>Delete all the posts</div>
  </my-post>
</blog>

Mixins

this.mixin(mixinObject)

Extends the current tag with functionality available on mixinObject. For example:

var OptsMixin = {
  // init method is a special one which can initialize
  // the mixin when it's loaded to the tag and is not
  // accessible from the tag its mixed in
  init: function() {
    this.on('updated', function() { console.log('Updated!') })
  },

  getOpts: function() {
    return this.opts
  },

  setOpts: function(opts, update) {
    this.opts = opts
    if (!update) this.update()
    return this
  }
}

<my-tag>
  <h1>{ opts.title }</h1>

  this.mixin(OptsMixin)
</my-tag>

riot.mixin(mixinName, mixinObject)

Register a shared mixin, globally available to be used in any tag: this.mixin(mixinName).

riot.mixin(mixinObject)

Register a global mixin, and automatically adds it to all tag instances.

Events

Each tag instance is an observable so you can use on and one methods to listen to the events that happen on the tag instance. Here’s the list of supported events:

For example:

// cleanup resources after tag is no longer part of DOM
this.on('unmount', function() {
  clearTimeout(timer)
})

Reserved words

The above method and property names are reserved words for Riot tags. Don’t use any of following as your instance variable or method name: opts, parent, tags, root, update, unmount, on, off, one and trigger. Variables beginning with an underscore (e.g.: this._item) are reserved for internal use too. Local variables can be freely named. For example:

<my-tag>

  // allowed
  function update() { }

  // not allowed
  this.update = function() { }

  // not allowed
  update() {

  }

</my-tag>

Manual construction

riot.tag(tagName, html, [css], [attrs], [constructor])

Creates a new custom tag “manually” without the compiler.

Example

riot.tag('timer',
  '<p>Seconds Elapsed: { time }</p>',
  'timer { display: block; border: 2px }',
  'class="tic-toc"',
  function (opts) {
    var self = this
    this.time = opts.start || 0

    this.tick = function () {
      self.update({ time: ++self.time })
    }

    var timer = setInterval(this.tick, 1000)

    this.on('unmount', function () {
      clearInterval(timer)
    })

  })

See timer demo and riot.tag API docs for more details and limitations.

Warning by using riot.tag you cannot enjoy the advantages of the compiler and the following features are not supported:

  1. Self-closing tags
  2. Unquoted expressions. Write value="{ val }" instead of value={ val }
  3. Boolean attributes. Write __checked="{ flag }" instead of checked={ flag }
  4. Shorthand ES6 method signatures
  5. <img src={ src }> must be written as <img riot-src={ src }> in order to avoid illegal server requests
  6. style="color: { color }" must be written as riot-style="color: { color }" so that style attribute expressions work in IE
  7. Scoped CSS precompilation.

You can take advantage of <template> or <script> tags as follows:

<script type="tmpl" id="my_tmpl">
  <h3>{ opts.hello }</h3>
  <p>And a paragraph</p>
</script>

<script>
riot.tag('tag-name', my_tmpl.innerHTML, function(opts) {

})
</script>

riot.Tag(impl, conf, innerHTML)

experimental

In riot 2.3 we gave you the access to the internal Tag instance in order to let you create your custom tags in more creative ways.

For example using ES2015:


class MyTag extends riot.Tag {
  constructor(el) {
    super({ tmpl: MyTag.template() }, { root: el })
    this.msg = 'hello'
  }
  bye() {
    this.msg = 'goodbye'
  }
  static template() {
    return `<p onclick="{ bye }">{ msg }</p>`
  }
}

new MyTag(document.getElementById('my-div')).mount()

The riot.Tag method is not recommended. You should use it only if you need to achieve special features not available with the previous riot methods