LoginSignup
3
1

More than 3 years have passed since last update.

Nuxt.js、Firestore、axiosでデータの投稿日時表示、ソート機能実装

Last updated at Posted at 2020-12-01

この記事の概要

↓以前書いた記事で作った掲示板アプリの追加実装を行います。
Nuxt.js、Firebase、axiosでパパッと掲示板!

※※※
前回からの続きになっております
以下、適宜axiosメソッドに渡しているURLのYOUR_PROJECT_IDを自分のプロジェクトIDに置き換える必要があることに注意してください。
YOUR_PROJECT_IDのままだと以下のエラーが出ます。
スクリーンショット 2020-11-24 20.39.13.png


追加するのは

・投稿日時の表示
・投稿日時順にソート

目標物

demo

demo

追加で導入するもの

moment (時刻フォーマットの整形用)
lodash (ソート用)

moment

ターミナル
$ npm install --save moment
pages/index.vue
<script>
import moment from 'moment';

lodash

導入方法は以下参照ください。
webpack プラグインを追加するには?

nuxt.config.js
import webpack from 'webpack'
export default {

  //・・・・・・省略

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {
    plugins: [
      new webpack.ProvidePlugin({
        _: 'lodash'
      })
    ]
  }
}

投稿日時の表示

送るデータにcreatedを追加

pages/index.vue
<script>
//・・・・・・・・・・・省略
  methods: {
    submitPosts() {
      this.$axios
        .$post(
          'https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/posts',
          {
            fields: {
              name: {
                stringValue: this.name
              },
              comment: {
                stringValue: this.comment
              },
//------------↓ここから--------------
              created: {
                timestampValue: new Date()
              }
//------------↑ここまで--------------
            }
          }
        )
        .then(() => {
          this.name = '';
          this.comment = '';
          this.getPosts();
        });
//・・・・・・・・・・・省略
</script>

そして表示

pages/index.vue
<template>

      <p>名前:{{post.fields.name.stringValue}}</p>
      <br>
      <p>コメント:{{post.fields.comment.stringValue}}</p>
      <br>
<!-----↓ここから-------------------------------------------------------->
      <p>投稿日時:{{post.fields.created.timestampValue}}</p>
      <br>
<!-----↑ここまで-------------------------------------------------------->
    </div>
  </div>
</template>

今こんな感じです。

スクリーンショット 2020-11-28 19.57.35.png

あまり見慣れないフォーマットなのでわかりやすく整形します。


filterを使ってフォーマットを整形してあげましょう。
さらにここでmomentを使用しています。

pages/index.vue
<script>
//・・・・・・・・・・・省略
    getPosts() {
      this.$axios.$get(
        "https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/posts"
      )
      .then(res => {
        this.posts = res.documents;
      });
    }
  },
//------------↓ここから--------------
  filters: {
    dateFilter(date) {
      return moment(date).format('YYYY/MM/DD HH:mm:ss');
    }
  }
//------------↑ここまで--------------
};
</script>
pages/index.vue
<template>
<!-----省略-------------------------->

      <p>投稿日時:{{post.fields.created.timestampValue | dateFilter}}</p>

<!-----省略--------------------------->
</template>


こうなったらOKです。
スクリーンショット 2020-11-28 20.08.25.png


投稿日時でソートさせる

現状はこんな感じです。
これをソートさせて行きます。

スクリーンショット 2020-11-28 20.13.30.png

lodash_.orderBy関数を使います

第一引数にソートしたい配列もしくはオブジェクト。
第二引数に値を渡します。

pages/index.vue
<script>
//・・・・・・・・・・・省略
    getPosts() {
      this.$axios.$get(
        "https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/posts"
      )
      .then(res => {
//-----------------------↓ここ--------------
        this.posts = _.orderBy(res.documents, 'fields.created.timestampValue');
      });
    }
  },
  filters: {
    dateFilter(date) {
      return moment(date).format('YYYY/MM/DD HH:mm:ss');
    }
  }
};
</script>

スクリーンショット 2020-11-28 20.17.22.png


OKです。
最後に昇順、降順を切り替えられる様にします。

昇順、降順の切り替え

pages/index.vue
<template>
  <div>
    <h1>掲示板!</h1>
    <br>名前
    <div>
      <input type="text" v-model="name">
    </div>コメント
    <div>
      <textarea v-model="comment"></textarea>
    </div>
    <br>
    <button @click="submitPosts">投稿する</button>
    <br>
    <br>
    <h2>投稿一覧</h2>
<!-----↓ここから-------------------------------------------------------->
    <select v-model="selected" @change="getPosts">
      <option>新しい順</option>
      <option>古い順</option>
    </select>
<!-----↑ここまで-------------------------------------------------------->


<!-----省略-------------------------->


</template>

<script>
import moment from 'moment';
export default {
  data() {
    return {
      name: '',
      comment: '',
      posts: [],
//--------↓ここ--------------
      selected: '新しい順'
    };
  },


//・・・・・・・・・・・省略
</script>

まずプルダウンを用意します
「新しい順」←→「古い順」と切り替わるごとにselectedにその値が入ります、
selectedのデフォルトの値は「新しい順」としておきます。
さらに切り替わるごとにgetPostsメソッドを呼びリストレンダリングをします。


pages/index.vue
<script>
//・・・・・・・・・・・省略
    getPosts() {
      console.log('getPost')
      this.$axios
        .$get(
          'https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/posts'
        )
        .then(res => {
          switch (this.selected) {
            case '新しい順':
              this.posts = _.orderBy(res.documents, 'fields.created.timestampValue');
              break;
            case '古い順':
              this.posts = _.orderBy(res.documents, 'fields.created.timestampValue', 'desc');
              break;
          }
        });
    }
  },
//・・・・・・・・・・・省略
</script>

_.orderByの第三引数に'desc'を渡すことで降順になります。
switch文でselectedの値が「新しい順」なら昇順、「古い順」なら降順とします。

※第三引数に'asc'を渡すことで昇順を指定することもできます。

完成!

pages/index.vue
<template>
  <div>
    <h1>掲示板!</h1>
    <br>名前
    <div>
      <input type="text" v-model="name">
    </div>コメント
    <div>
      <textarea v-model="comment"></textarea>
    </div>
    <br>
    <button @click="submitPosts">投稿する</button>
    <br>
    <br>
    <h2>投稿一覧</h2>
    <select v-model="selected" @change="getPosts">
      <option>新しい順</option>
      <option>古い順</option>
    </select>
    <br>
    <div v-for="post in posts" :key="post.id">
      <hr>
      <br>
      <p>名前:{{post.fields.name.stringValue}}</p>
      <br>
      <p>コメント:{{post.fields.comment.stringValue}}</p>
      <br>
      <p>投稿日時:{{post.fields.created.timestampValue | dateFilter}}</p>
      <br>
    </div>
  </div>
</template>

<script>
import moment from 'moment';
export default {
  data() {
    return {
      name: '',
      comment: '',
      posts: [],
      selected: '新しい順'
    };
  },
  created() {
    this.getPosts();
  },
  methods: {
    submitPosts() {
      this.$axios
        .$post(
          'https://firestore.googleapis.com/v1/projects/vue-test-df33d/databases/(default)/documents/posts',
          {
            fields: {
              name: {
                stringValue: this.name
              },
              comment: {
                stringValue: this.comment
              },
              created: {
                timestampValue: new Date()
              }
            }
          }
        )
        .then(() => {
          this.name = '';
          this.comment = '';
          this.getPosts();
        });
    },
    getPosts() {
      this.$axios
        .$get(
          'https://firestore.googleapis.com/v1/projects/vue-test-df33d/databases/(default)/documents/posts'
        )
        .then(res => {
          switch (this.selected) {
            case '新しい順':
              this.posts = _.orderBy(res.documents, 'fields.created.timestampValue');
              break;
            case '古い順':
              this.posts = _.orderBy(res.documents, 'fields.created.timestampValue', 'desc');
              break;
          }
        });
    }
  },
  filters: {
    dateFilter(date) {
      return moment(date).format('YYYY/MM/DD HH:mm:ss');
    }
  }
};
</script>

お疲れさまでした!
最終的に記事上部の目標物の様になっていればOKです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1