Riot.jsでobservableを使って簡易的な通知メッセージを表示する

たとえばログインが完了したときとか、データの保存に成功したときとか、
ユーザーに対して処理の結果を　簡易的にフィードバックしたいことがあるわけです。

Railsだとflashという仕組みで簡単にできますね。

>[flash - Railsドキュメント](http://railsdoc.com/references/flash)

これをRiot.jsでもやりたい！ということでやってみました。

デザインにはおしゃれで有名なSemanticUIを使っていますが、bootstrapとかでも同じような書き方できるはず。SemanticUIおすすめ。

## 完成イメージ
![flash.gif](https://qiita-image-store.s3.amazonaws.com/0/11704/fc21e028-df5a-b60b-8fdd-02a6aa6cc79b.gif)


## 環境
- riot.js v3.0.0
- SemanticUI v2.2.4

きましたv3！

## メッセージを別タグにして読み込む
ログイン完了したあととかって、だいたい画面遷移するじゃないですか。
なので通知メッセージはタグ横断で表示したい。

ということでまずはメッセージ部分をflash.tagとして切り出し、
index.htmlでもろもろ読み込みの設定をします。
（ページごとの内容を`<content>`に出力するSPA的な想定です）

```html:index.html
...
<body>
  <header></header>
  <div>
    <flash></flash><!-- ここにメッセージ表示するよ -->
    <content></content>
  </div>
  <footer></footer>

　...

  <script>
    ...
    var obs = riot.observable();
  </script>
</body>
```


### observableつかうよ
```js
var obs = riot.observable();
```

タグ間で動作を連携させたいので、observableを使います。
というか今回はじめてつかった。便利！

ここではまだobservableを用意しただけ。
この後こいつのイベントを発火させ、それを受け取ることで、タグ間で動作を連携させます。

こちらの記事が大変わかりやすかったです。
>[【Riot.js】タグ間で動作を連動させる - Qiita](http://qiita.com/iwamatsu0430/items/49ea5ad14c631f323d22)


## flash.tagを実装する
お次は`flash.tag`の中身を実装します。これが今回のメイン。

html部分はSemanticUIの[message](http://semantic-ui.com/collections/message.html)をほぼそのまま使ってるだけなので、非常にシンプル。cssもお好みで調整してください。

flashオブジェクトを受け取ったらメッセージが表示されるようになってて、`flash.type`と`flash.text`でメッセージの色と本文を設定できるようにしています。
(typeには`success`とか`error`とかが入るイメージ）

```html:flash.tag
<flash>
  <div id="flasher" if={flash}>
    <div class="ui attached message {flash.type}">
      <i class="close icon" onclick={ close }></i>
      <div class="header">{flash.text}</div>
    </div>
  </div>


  <style>
    #flasher {
      width: 100%;
      position: fixed;
      z-index: 100;
      opacity: 0.9;
    }
  </style>


  <script>
    var that = this

    close(ms=0) {
      setTimeout(function(){
        $('#flasher').transition('fade')
        that.flash = null
        that.update()
      }, ms)
    }

    obs.on("flashChanged", function(obj) {
      that.flash = obj
      that.update()
      that.close(3000)
    })
  </script>
</flash>
```

一番下で、さっきのobservableが`flashChanged`というトリガーを受け取ったときのイベントを定義しています。

といってもやってることは非常にシンプルで、flashオブジェクトを受け取って画面を更新してるだけです。

これだけでもいいのですが、今回は数秒たつと自動で消えるようにしたかったので、`close()`メソッドをを定義して最後に呼び出しています。

Semanticで用意してくれてる`transition('fade')`でふわっと消えるのがいい感じ。


## メッセージを表示する
最後にイベント発火側の記述。
これも非常にシンプルです。

```js:auth.tag
if(success) {
  obs.trigger("flashChanged", {type:'success',text:'ログインしました'})
}else {
  obs.trigger("flashChanged", {type:'error',text:'ログインに失敗しました'})
}
```

## おまけ
同じようにして、ページ全体にローディング画面を表示するタグも作ってみました。

```html:dimmer.tag
<dimmer>
  <div class="ui page dimmer {state}">
    <div class="ui indeterminate huge text loader">Loading</div>
  </div>

  <script>
    var that = this

    obs.on("dimmerChanged", function(state) {
      that.state = state
      that.update()
    })
  </script>
</dimmer>
```

```js:auth.tag
obs.trigger("dimmerChanged", 'active') 

signup().then(
  function() {
    obs.trigger("dimmerChanged", '')
  })
)
```

こんな感じになりました。

![capture.gif](https://qiita-image-store.s3.amazonaws.com/0/11704/b93b3de4-5dd0-36f5-5ae2-fcadd22b3609.gif)


## まとめ
という感じで非常にお手軽にメッセージ通知機能ができました。
observable便利！