̑

#Templating

#Anatomy

Everything is a component, Riot refers to them as tags Tags have to be mounted

<example>
    <b>Markup</b>
    <script>
        // Script
    </script>
</example>

#Expressions

#Pure JavaScript

Can contain any javascript except curly brackets

Random number: {Math.random() * 10}
&copy; <time datetime={new Date().getFullYear()}></time>
How long is a day in seconds? {60*60*24}

#Accessing tag properties

My name is {author.name}
and I'm {author.age} {unit}s old
<script>
    this.author = {
        name: 'Martin',
        age: 25
    }
this.unit = 'year'
</script>

#Foreach - loop data

#Array

<nav>
    <a href="#{doc}" each={doc in docs}>
        {doc}
    </a>
</nav>
<script>
    this.docs = [
        'templating',
        'tag',
        'mixin',
        'observable',
        'router'
    ]
</script>

You can access both index and value by providing a second argument

<nav>
    <a href="#{doc}" each={doc, index in docs}>
        {index + 1} - {doc}
    </a>
</nav>

#Object

Used for more complex structures, where each item has a distinct key

Objects use different order of key, value in the each statement

<card size={card.size} name={title}
      each={title, card in cards}>
</card>
<script>
    this.cards = {
        analytics : {
            size: 1,
            toolbar: ['reset']
        },
        posts: {
            size: 2,
            toolbar: ['add', 'list']
        }
    }
</script>

#Virtual

The virtual tag is used for loops that should generate no wrapper markup

<dl>
    <virtual each={item in items}>
        <dt>{item.key}</dt>
        <dd>{item.value}</dd>
    </virtual>
</dl>

#Conditionals

#Shorthand ternary

<div class={active: item.active}></div>

#Ternary

<div class={item.active ? 'active' : ''}></div>

#Blocklevel

Does not write HTML if condition is false

<div if={shop.items.length}></div>

#Hide

Writes HTML, just sets display style to none if condition is true

<nav hide={mobile}></nav>

#Show

Opposite of Hide display

<nav show={mobile}></nav>

#Access elements and tags

#HTML Elements

You can also use id if you are not comfortable with name

<input name="todo">
<script>
    this.todo.value = 'write todolist'
</script>

#Child tags

Access via name or id

<todo-item name="first"></todo-item>
<script>
    this.tags.first
</script>

If there are more instances, you get an array of tags

<todo-item></todo-item>
<todo-item></todo-item>
<todo-item name="last"></todo-item>
<script>
    this.tags['todo-item'] // Array<Tag> - 2
    this.tags.last // <Tag> - 1
</script>

#Options

Options can be passed via html params or on mount

Options only accept boolean, number, string or simple array, when passing values directly

#Passing values directly per HTML

<todo-item name="Finish Cheatsheet" done={false}>
</todo-item>
<script>
    // Script of todo-item
    this.opts.name // 'Finish Cheatsheet'
    this.opts.done // false
</script>

#Passing variables per HTML

<todo-item item={item}></todo-item>
<script>
    this.item = {
        name: 'Study riot',
        done: true
    }
</script>

#Passing values on Mount

On mount, we are more flexible, since we are in js See mount

var items = [
    {name: 'Share', done: true},
    {name: 'Star', done: true},
    {name: 'Work', done: false},
]
riot.mount('todo-list', items)

#Yield

Yielding is like options, just that it accepts HTML and other riot tags

Definition

<popup-body>
    <yield>
</popup-body>

Usage

<popup-body>
    Hi! I'm supporting
    <abbr title="Hypertext Markup Language">HTML</abbr>
</popup-body>

#Multiple Yieldpoints

Notice: This feature is supported in Riot 2.3.12 or later

Usage

<card>
    <yield to="toolbar">
        <a>Add post</a>
        <a>Recently published</a>
    </yield>
    <yield to="header">
        <i class="fa fa-text"></i> Posts
    </yield>
</card>

Definition

<card>
    <h2>
        <yield from="header" />
    </h2>
    <div class="toolbar">
        <yield from="toolbar" />
    </div>
</card>

#Tag

#Lifecycle events

#before-mount

Before the tag is mounted

this.on('before-mount', () => {
})

#mount

After all expressions are evaluated on mount

this.on('mount', () => {
})

#update

Allows recalculation of data before updating

this.on('update', () => {
})

#updated

After updates

this.on('updated', () => {
})

#before-unmount

Before the tag is removed

this.on('before-unmount', () => {
})

#unmount

After the tag is removed

this.on('unmount', () => {
})

#all events

Listen to all events You can fetch the event name if desired

this.on('*', (eventName) => {
})

#Tag Methods & Properties

#on, one, off, trigger

A riot tag already implements a riot.observable See observable

#Update

Shortcut for trigger this.trigger('update')

this.update()

#isMounted

Attribute to tell whether or not the tag is mounted

this.isMounted

#root

Points to it's own tag element

this.root // reference to riot tag

#opts

Options passed via HTML or on mount, See options

#mixin

See Mixins

#tags

See Child tags

#parent

Access the parent tag, if there is one

this.parent // <Tag>

#Riot

#mount

Mounting a tag will make it appear on your webpage/app There are various ways to mount your tags

#All

This will mount all tags and their children tags

Notice: This will not mount dynamically loaded tags such as with a router

riot.mount('*')

#Specific with options

When mounting a tag, you can pass options, accessible as opts

<todo-list></todo-list>
<script>
    var items = [
        'fork',
        'star',
        'contribute'
    ]
    riot.mount('todo-list', items)
</script>

#Data attribute

Notice: This feature is supported in Riot 2.3.17 or later With a data attribute, you can mount a tag into an element

<ul data-is="todo-list"></ul>
<script>
    // You can mount all or with data too here
    riot.mount('todo-list')
</script>

#Mount to DOM node

You can also use a DOM node to mount your tag

<main name="content">
<script>
    // At maximum, riot.mount takes three arguments
    riot.mount(this.content, 'todo-list', {items: ['be nice', 'share your knowledge', 'give feedback']})
</script>

#observable

Turns a non-riot object/class into an observable, being capable of triggering and listening to events This will add trigger, on, one and off to the provided object See Observable for all methods

class AuthService {
    constructor() {
        riot.observable(this)
    }
}

#Mixins

#Mixin anatomy

A mixin can be a function, object or class Mixins have, after initializing them, access to your tag

var authService = {
    init: () => {
        // Called upon initializing the mixin
    },
    login: (user, pass) => {//...}
}

#Initializing

#Inline Usage

For global objects or dynamic mixins within the tag

this.mixin(authService)

#Shared Mixin

Share your mixin across tags

// In global scope
riot.mixin('auth-service', authService)
// In your tag
this.mixin('auth-service')

#Global Mixin

Add mixin to every mounted tag

// In global scope BEFORE mounting
riot.mixin(authService)

#Observable

Great to create tag-based API For use outside tags, see

#Trigger

Trigger custom events similar update

#Simple trigger

this.trigger('selected', items)

#Trigger with data

this.trigger('selected', items)

#Listening to triggers

From inside the tag or parent/child tag You can use them for lifecycle events too.

#Always listen

this.on('selected', (items) => {
    // Do something with the selected items
})

#Listen once

this.one('selected', (items) => {
    // Do something with the selected items
})

#Stop listening

this.off('selected')

#Router

The router takes care of the history pushState

Depending on route, you can mount different tags, update data and so on.

#Minimal setup

#Setup

The function works with any amount of parameters

Recommendation: Put your routing setup within this.on('mount', () => {}) in your main tag, that controls everything (e.g. app.html)

<main name="content"></main>
<script>
riot.route((collection, action, id) => {
    // Mount another tag, or do something with the data
    riot.mount(this.content, collection, {view: action, id: id})
})
</script>

#Go to Route

This will call the route method defined above Where customer is collection, edit is action and 289 is id

riot.route('customer/edit/289')

#Start listening

This starts the router, and examines the hash that is already in place Notice: This feature is supported in Riot 2.3 or later

riot.route.start(true)

In earlier versions of riot, this was done with

riot.route.start()
riot.route.exec()

You can also separately set them up, if you like to

#Advanced setup

In the advanced setup, you can set up a function per route call and you are more flexible with wildcard support

Notice: These features are only supported on Riot 2.3 or later

#Route without wildcard

riot.route('/index', () => {})

#Route with wildcard

Regex for wildcards:

* ([^/?#]+?)

.. .*

This route will catch everything that is a subroute of blog

riot.route('/blog/*', (entry) => {})

You can setup more distinct variables, other than splitting /

riot.route('/blog/*-*/*', (month, year, entry) => {
    // route might look like /blog/06-2012/give-me-lasagna
})

Everything after a keyword

riot.route('/old..', () => {
    // Sorry, this page has been removed
})

#Subroutes

Subroutes overwrite existing routes, based on context

var subRoute = riot.route.create()
subRoute('/blog/tags', () => {
    // Instead of looking for a post named tags
    // List all tags used in posts
})