Vue.jsでGETとPOSTを実装する

Vue.jsにおけるGET・ POSTに関する情報がほとんどない([公式のREADME](https://github.com/vuejs/vue-resource)くらい)ので、上手くいった例をまとめておく。

GET/POSTにはvue-resoureを用いた。
この辺の処理はAngularJSとよく似ているので、Vue.jsで調べるよりAngularJSで調べた方がヒントは得られるかもしれない。

#GET
イベントのリストをJSONで返してくれるAPIに対してGETをして、その結果を表示する例。
[【GitHub】](https://github.com/growsic/JS/blob/master/VueJS/vueGETPOST/vueGET.js)
##HTMLの実装
HTMLはシンプルで、js内でelに登録するidのhomeと、v-repeatでeventsの中の要素を取得して表示している。

```html
  <div id="home">
    <h1>event list</h1>
    <hr>
    <div v-repeat="t : events">
        {{$index}}
        <h2>{{t.title}}</h2>
        <p>{{t.description}}</p>
        <p>{{t.date}}</p>
        <p>{{t.location}}</p>
        <hr>
    </div>
    <div>
    </div>
</div>
```
それぞれの細かい説明は、[3つだけ覚えてVue.jsでtodoアプリを作ってみる](http://qiita.com/growsic/items/bf97c8627c208b4c88a7)を参照。

##JSの実装
vue-resourceを使ってGETメソッドを行っている。
基本形は

```js
 this.$http.get(URL, function (data, status, request) {
                //GETメソッドが成功した場合の処理
            }).error(function (data, status, request) {
                //GETメソッドが失敗した場合の処理
            })
    }
```
引数のdataはGETメソッドで取得されたデータが配列で、statusにはGETメソッドの結果が格納される。

* 取得したデータを呼び出したいときはdata[index]ようにして取り出す
* GETメソッドがうまくいったか確認したい場合はconsole.logでstatusを出力する

ようにしてやれば良い。


```js
  var app = new Vue({
    //select html element
    el: '#home',
    //init data
    data: {
        events: [],
        someData: [],
        input: ""
    },
    //called when loaded
    created: function(){
        // GET request
        var self = this
          this.$http.get('http://example.com/forGET', function (data, status, request) {
                for(var i = 0; i < data.length; i++){
                    this.events.push(data[i]);
                }
            }).error(function (data, status, request) {
                // handle error
            })
    },
  })
```

今回の例では、GETメソッドが成功した場合、dataからenventsリストにforループで受け取った値を格納している。
eventsの要素はv-repeatにリアルタイムに反映されるようにしているので、このforループ内においてその場で反映される。

#POST
Vue.jsでPOSTをする例として、イベントの作成フォームを作った。

* 入力に応じてリアルタイムでエラー情報を表示する(validation)
* 1回作成ボタンを押すまではエラー情報は出ない
* 作成ボタンを押すと、入力にエラーがなければ POSTする

ようになっている。
Vue.jsでのvalidationの方法については
[Vue.jsでフォームのvalidationを行う](http://qiita.com/growsic/items/fb57552053cf90f0fc31)
を参照のこと。

##フォームのイメージ
![vue.jsのフォームイメージ](https://qiita-image-store.s3.amazonaws.com/0/78136/61918734-53bb-250b-1ced-d446ddb30ce6.png)

#具体的な実装方法
##[event-new.html](https://github.com/growsic/JS/blob/master/VueJS/vueGET/event-new.html)の実装
HTMLは[Vue.jsでフォームのvalidationを行う](http://qiita.com/growsic/items/fb57552053cf90f0fc31)とほぼ一緒。
主にjsのaddEventメソッドが今回の主な実装。

HTMLの変更点としては

```html
<ul id="errors" class="display-none">
```
の1行。
"1回作成ボタンを押すまではエラー情報は出ない"ようにするために、idを振ってdisplay-noneクラスを指定してる。
display-noneクラスは単にdisplay:noneにしているだけ。

###v-ifやv-showで表示/非表示をやらない理由
Vue.jsのv-ifやv-showでbooleanを渡して表示/非表示を切り替える方法もある。
しかし、**表示した一瞬、エラー情報が表示されてしまう。**
これはJSの処理がDOMツリーが構築より後に行われているため。
 DOMツリーが構築されて表示された後に、v-ifやv-showが評価されて、falseなら非表示になる。
したがって、エラー情報が一瞬表示された後に消える。

最初から表示されないようにするためには、**CSSでdisplay:noneにしておいて、のちにJSで表示を変える**のが良い。

[event-new.html](https://github.com/growsic/JS/blob/master/VueJS/vueGET/event-new.html)

```html
<div id="app">
      <form id="form" v-on="submit:addEvent">
        <!-- それぞれに作ったvaidatorに通す -->
        <p>title:<input v-model="newEvent.title | titleValidator"  name='title' value=''></p>
        <p>description:<textarea v-model="newEvent.description | descriptionValidator" name='description' value=''></textarea></p>
        <p>date:<input v-model="newEvent.date | dateValidator" name='date' value=''></p>
        <p>location:<input v-model="newEvent.location | locationValidator" name='location' value=''></p>
        <input type="submit" value="イベントを作成">
      </form>
      <!-- error表示欄 -->
      <ul id="errors" class="display-none">
        <!-- you need to implement "display-none" class which is simply display nothing -->
        <li v-show="!validation.title">タイトルが未入力です</li>
        <li v-show="!validation.description">説明が未入力です</li>
        <li v-show="!validation.date">日付が未入力です</li>
        <li v-show="!validation.location">場所が未入力です</li>
      </ul>

    </div>
```

##[event_add.js](https://github.com/growsic/JS/blob/master/VueJS/vueGET/event_add.js)の実装

validation周りは[Vue.jsでフォームのvalidationを行う](http://qiita.com/growsic/items/fb57552053cf90f0fc31)とほぼ一緒。

###POSTの実装
POSTには[vue-resource](https://github.com/vuejs/vue-resource)を使う。

```js
    // POST
    this.$http.post('http://example.com/forPOST', this.newEvent, function (data, status, request) {
          console.log("post success")
          //status check
          console.log(status)

          }).error(function (data, status, request) {
            console.log("post failed")
     })
```

引数に

* URL
* POSTするパラメータ
* 成功した場合の処理

を渡し、エラーした場合の処理を追加する。
functionの引数のstatusの値を確認することで、POSTが成功したか否かを確認できる。


[event_add.js](https://github.com/growsic/JS/blob/master/VueJS/vueGET/event_add.js)

```js
var add = new Vue({

// element to mount to
el: '#app',

// initial data
data: {
  users: [],
  newEvent: {
    title: '',
    description: '',
    date: '',
    location: ''
  },
  validation: {
    title: false,
    description: false,
    date: false,
    location: false
  }
},

// validation 個別に作っているので、評価の仕方を変えられる
filters: {
  titleValidator: {
    write: function (val) {
      this.validation.title = !!val
      return val
    }
  },
  descriptionValidator: {
    write: function (val) {
      this.validation.description = !!val
      return val
    }
  },
  dateValidator: {
    write: function (val) {
      this.validation.date = !!val
      return val
    }
  },
  locationValidator: {
    write: function (val) {
      this.validation.location = !!val
      return val
    }
  }
},

// computed property for form validation state
computed: {
  isValid: function () {
    var valid = true
    for (var key in this.validation) {
      if (!this.validation[key]) {
        valid = false
      }
    }
    return valid
  }
},

// methods
methods: {
  addEvent: function (e) {
    document.getElementById("errors").className = ""
    e.preventDefault()
    if (this.isValid) {
      console.log("success")
      console.log("title: " + this.newEvent.title)
      console.log("description: " + this.newEvent.description)
      console.log("date: " + this.newEvent.date)
      console.log("location: " + this.newEvent.location)

      // POST
        this.$http.post('http://example.com/forPOST', this.newEvent, function (data, status, request) {
          console.log("post success")
          //status check
          console.log(status)


          }).error(function (data, status, request) {
            console.log("post failed")
          })

    }else{
      console.log("need edit")
    }
  },
}
})
```
## Vue.js参考書籍
[Vue.js入門 基礎から実践アプリケーション開発まで](https://www.amazon.co.jp/gp/product/B07J6FP6NQ/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B07J6FP6NQ&linkCode=as2&tag=hirocode-22&linkId=5614b4d30cf87df8eb08e657dacdfdb7)