見出し画像

Webアプリ開発(Django+Vue.js+Docker)#11

こちらの記事の続きになります。

今回は、テストの出題範囲をプルダウンメニューで絞り込む部分と、解答ボタンにより表示非表示を切り替える部分を作成しましょう。

バックエンド

なんと、、、もう終わっているのです。。
そう、今回はフロントエンドだけの処理で可能です。

フロントエンド

プルダウンに関しては、登録したテストを絞り込むプルダウンメニューと全く同じです。

プルダウンメニュー

<!-- 初期画面は非表示 -->
<div id="show">
  <!-- フィルタリング -->
  <div>
    <div style="display: flex;">
      <div>テスト:</div>
      <select @change="detectChange" v-model="selected">
        <option value="全て">全て</option>
        <option v-for="subject, index in subjects" :value="subject.subject">[[ subject.subject_name ]]</option>
      </select>
    </div>

ただ、プルダウンと文字を並列させるためにCSSを使用しています。

次は、これに対するVue関数を記述していきます。
ここで、これに関しても登録したテストの絞り込み機能同様、ページが正解/不正解ボタンを押すことでリロードされたときに毎回プルダウンが初期化されては面倒なので、Cookieを使用して選択項目を記憶させておくようにします。

new Vue({
    el: '#show',
    delimiters: ['[[', ']]'],
    data: {
      subjects: subjectList,
      selected: '',
      test: testList[Math.floor(Math.random()*testList.length)],
    },
    /* ページ読み込み時に実行される部分 */
    mounted: function(){
      //Cookieを全て取得
      var cookies = document.cookie;

      //取得したCookieを分割する
      var cookiesArray = cookies.split(';');
      var cookie = -1;
      for(var c of cookiesArray){
        var cArray = c.split('=');
        if(cArray[0] == 'pulldown'){
          //console.log(cArray);
          cookie = cArray[1];
        }
      }

      /* プルダウンの初期値設定 */
      if(cookie === -1){
        //cookieに何も登録されていない時
        this.selected = '全て';
      }else{
        this.selected = cookie;
      }

      var tests = [];
      //フィルタを掛けてデータを抽出する
      for(let i=0;i<testList.length;i++){
        if(this.selected=== '全て'){
          tests.push(testList[i]);
        }else if(this.selected === testList[i].subject){
          tests.push(testList[i]);
        }
      }
      this.test = tests[Math.floor(Math.random()*tests.length)];
    },
    methods: {
      /* プルダウンメニューと同期させる処理 */
      detectChange: function(e) {
        /* 初期化 */
        var tests = [];

        //cookieにプルダウンの値を登録する(有効期限180秒)
        document.cookie = 'pulldown=' + e.target.value + ';max-age=180';

        //フィルタを掛けてデータを抽出する
        for(let i=0;i<testList.length;i++){
          if(e.target.value=== '全て'){
            tests.push(testList[i]);
          }else if(e.target.value === testList[i].subject){
            tests.push(testList[i]);
          }
        }
        this.test = tests[Math.floor(Math.random()*tests.length)];
      },
    },
  })

同じですね。
違う部分は、登録したテスト確認画面では、表示するテストが複数だったのに対し、今回は一つになっているというところだけですかね。。

これで、プルダウンメニュに関してはできました!

解答表示ボタン

それでは、解答の表示/非表示を切り替えるボタンを作成していきましょう。

HTMLの方では以下のように、解答の部分のネストを一つ下げてVueの関数で囲い、一つボタンを配置するだけです。

<!-- 解答部分 -->
  <div v-show="!isActive">
    <div class="card">
      <h5 class="card-header">解答</h5>
      <div class="card-body">
        <h5 class="card-title"></h5>
        <p class="card-text">[[ test.ans ]]</p>
      </div>
      <p class="info">
        正答率:[[ test.percent ]]%<br>
        出題数:[[ test.total ]]
      </p>
      <form method="post" action="{%url 'test:exam' %}">
        {% csrf_token %}
        <input type="hidden" name="test_id" :value="[[ test.id ]]">
        <button type="submit" class="btn btn-primary" name="correct">正解</button>
        <button type="submit" class="btn btn-danger" name="uncorrect">不正解</button>
      </form>
    </div>
  </div>
  <button type="submit" class="btn btn-primary" @click="changeShow">解答を見る</button>
</div>

それではこの部分の表示/非表示を切り替える関数(changeShow)を書いていきましょう。
ここに関しては、ページ読み込み時ではなく、常に監視しておいてほしい部分なので、methodsの方に書きます。

new Vue({
    el: '#show',
    delimiters: ['[[', ']]'],
    data: {
      subjects: subjectList,
      selected: '',
      isActive: true,
      test: testList[Math.floor(Math.random()*testList.length)],
    },

methods: {
      /* テスト画面で解答を表示させる処理 */
      changeShow: function() {
        this.isActive = !this.isActive;
      },

これだけ、、

isActiveをVueの監視対象に入れ、methods内の関数でボタンがクリックされるたびに!=isActiveと反転させる処理を書けばよいだけです。

それでは確認してみてください。
実際に初めは解答部分が隠れていますが、解答を見るボタンを押すことで解答が表示され、正解/不正解を登録できるようになりました。

これでほとんどの機能ができました!!!

それでは次はいよいよログイン機能を実装していきたいと思います。


いいなと思ったら応援しよう!