PythonでVue.jsソート(昇順・降順)

  • 2020.11.12
  • 2021.01.24
  • Flask
PythonでVue.jsソート(昇順・降順)

この記事からの続きとなります。
まだご覧になっていない方はどうぞ。

タイトルの通り昇順のソートを行います。

昇順

index.htmlを編集します。

まずは無駄なコードが多いためシンプルにします。

  <div id="sample_app">
    <table class="table table-striped">
      <thead>
        <tr>
          <th v-for="(column, key) in columns">
            [[ column ]]
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="result in results">
          <td v-for="(colum, key) in columns">
            [[ result[key] ]]
          </td>
        </tr>
      </tbody>
    </table>
  </div>

~~~~~~
~~~~~~
 <script>
   new Vue({
      el: '#sample_app',
      delimiters: ['[[', ']]'], // Flaskのdelimiterとの重複を回避
      data: {
        results: [],
        columns: null,
      },
        created() {
          axios.get('/json')
          .then(response => {
          this.results = response.data;
          })
          .catch(error => {
          console.log(error);
          });
          this.columns = {
            number : '#',
            age    : 'AGE',
            b      : 'B',
            chas   : 'CHAS',
            crim   : 'CRIM',
            dis    : 'DIS',
            indus  : 'INDUS',
            lstat  : 'LSTAT',
            nox    : 'NOX',
            ptratio: 'PTRATIO',
            rad    : 'RAD',
            rm     : 'RM',
            tax    : 'TAX',
            zn     : 'ZN',
          }
        },
  });
 </script>
$ main.py
http://127.0.0.1:5000/index

にアクセスして前回同様に表示されていればOKです。

次にソートメソッドを実装します。
sort_key: ”の追加と
createdの下にメソッドを実装します。

<script>
 data: {

  sort_key: ''
 },
 created() {


 },
 methods: {
  sort(key) {
   this.sort_key = key
   this.results.sort((a, b) => {
    if (a[this.sort_key] < b[this.sort_key]) return -1;
    if (a[this.sort_key] > b[this.sort_key]) return 1;
    return 0;
   });
  return this.results;
  }
 }
</script>

実装が終わったらテーブルの項目をクリックするとソートできる仕様にしたいため、@clickというメソッドを仕掛けます。
jqueryが必要なため簡易的なjqueryをインポートします。

<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>

続いて@click=”sort(key)を追記します。

<tr>
 <th v-for="(column, key) in columns" @click="sort(key)">
  [[ column ]]
 </th>
</tr>

サーバーを再起動して再度下記へアクセスしてthの部分をクリックしてみて下さい。

http://127.0.0.1:5000/index

ソート前

thをクリックどれでもいいです!
ソート(昇順)されればOK!

上の画像はサンプルです。LSTATが昇順でソートされているのが分かります。

ここまでの全体コードです。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Document</title>
</head>
<body>
  <h1>BOSTON DF</h1>
  <div id="sample_app">
    <table class="table table-striped">
      <thead>
        <tr>
          <th v-for="(column, key) in columns" @click="sort(key)">
            [[ column ]]
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="result in results">
          <td v-for="(colum, key) in columns">
            [[ result[key] ]]
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
  <script>
    new Vue({
      el: '#sample_app',
      delimiters: ['[[', ']]'], // Flaskのdelimiterとの重複を回避
      data: {
        results: [],
        columns: null,
        sort_key: ''
      },
        created() {
          axios.get('/json')
          .then(response => {
          this.results = response.data;
          })
          .catch(error => {
          console.log(error);
          });
          this.columns = {
            number : '#',
            age    : 'AGE',
            b      : 'B',
            chas   : 'CHAS',
            crim   : 'CRIM',
            dis    : 'DIS',
            indus  : 'INDUS',
            lstat  : 'LSTAT',
            nox    : 'NOX',
            ptratio: 'PTRATIO',
            rad    : 'RAD',
            rm     : 'RM',
            tax    : 'TAX',
            zn     : 'ZN',
          }
        },
        methods: {
          sort(key) {
            this.sort_key = key
            this.results.sort((a, b) => {
              if (a[this.sort_key] < b[this.sort_key]) return -1;
              if (a[this.sort_key] > b[this.sort_key]) return 1;
              return 0;
            });
            return this.results;
          }
        }
    });
  </script>
</body>
</html>

降順

続きまして降順の処理を追記していきたいと思います。

index.htmlを編集します。

body内の変更と
dataとmethodsに下記を追記します。sort()メソッドも若干編集します。

sortByにkeyを渡してsortByメソッド内でsort()メソッドを実行する使用に変更しました。

<body>
 <thead>
  <tr>
   <th v-for="(column, key) in columns" @click="sortBy(key)">



</body>
<script>
 data:{
 
 sort_asc: true,
 },
 methods: {
 sort() {
  if (this.sort_key != '') {
   let set = this.sort_asc ? 1 : -1;
   
   this.results.sort((a, b) => {
    if (a[this.sort_key] < b[this.sort_key]) return -1 * set;
    if (a[this.sort_key] > b[this.sort_key]) return 1 * set;
    return 0;
   });
    return this.results;
   } else {
    return this.results;
   }
 },
 sortBy(key) {
  this.sort_key === key ? (this.sort_asc = !this.sort_asc) : (this.sort_asc = true);
  this.sort_key = key;
  this.sort();
 },
},

</script>

thをクリックして昇順・降順が切り替わればOKです!

これだと昇順なのか降順なのか分かりにくいのでstyleで表示させたいと思います。

引き続きindex.htmlを編集します。

<head>

  <style>
		.asc::after {
  		content: "▼";
		}
		.desc::after {
			content: "▲";
		}
	</style>
</head>
<body>
 <thead>
  <tr>
   <th v-for="(column, key) in columns" @click="sortBy(key)" :class="sortAddClass(key)">>


</body>

<script>


 methods: {


  sortAddClass(key) {
   return {
    asc: this.sort_key === key && this.sort_asc,
    desc: this.sort_key === key && !this.sort_asc,
   };
  },
 }

</script>

thをクリックして▼が出ればOKです。

ソートうまくできたでしょうか。

index.htmlの全体コードも載せておきます。
参考になれば幸いです。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
		.asc::after {
  		content: "▼";
		}
		.desc::after {
			content: "▲";
		}
	</style>
</head>
<body>
  <h1>BOSTON DF</h1>
  <div id="sample_app">
    <table class="table table-striped">
      <thead>
        <tr>
          <th v-for="(column, key) in columns" @click="sortBy(key)" :class="sortAddClass(key)">
            [[ column ]]
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="result in results">
          <td v-for="(colum, key) in columns">
            [[ result[key] ]]
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
  <script>
    var vm = new Vue({
      el: '#sample_app',
      delimiters: ['[[', ']]'], // Flaskのdelimiterとの重複を回避
      data: {
        results: [],
        columns: null,
        sort_key: '',
        sort_asc: true,
      },
        created() {
          axios.get('/json')
          .then(response => {
          this.results = response.data;
          })
          .catch(error => {
          console.log(error);
          });
          this.columns = {
            number : '#',
            age    : 'AGE',
            b      : 'B',
            chas   : 'CHAS',
            crim   : 'CRIM',
            dis    : 'DIS',
            indus  : 'INDUS',
            lstat  : 'LSTAT',
            nox    : 'NOX',
            ptratio: 'PTRATIO',
            rad    : 'RAD',
            rm     : 'RM',
            tax    : 'TAX',
            zn     : 'ZN',
          }
        },
      methods: {
        sort() {
          if (this.sort_key != '') {
            let set = this.sort_asc ? 1 : -1;
            this.results.sort((a, b) => {
              if (a[this.sort_key] < b[this.sort_key]) return -1 * set;
              if (a[this.sort_key] > b[this.sort_key]) return 1 * set;
              return 0;
            });
            return this.results;
          } else {
            return this.results;
          }
        },
        sortBy(key) {
          this.sort_key === key ? (this.sort_asc = !this.sort_asc) : (this.sort_asc = true);
          this.sort_key = key;
          this.sort();
        },
        sortAddClass(key) {
          return {
            asc: this.sort_key === key && this.sort_asc,
            desc: this.sort_key === key && !this.sort_asc,
          };
        },
      },
        
    });
  </script>
</body>
</html>

Flaskカテゴリの最新記事