kintone と Vue.js は相性がいい? Vue.js で独自のビューと検索フォームを作ってみよう

著者名: 村濱 一樹 (External link) (kintone エバンジェリスト)

目次

はじめに

Vue.js (External link) は非常にシンプルな JavaScript フレームワークで、kintone と相性がよく、私自身 kintone のカスタマイズでは Vue.js を使うことも多いです。
今回は、Vue.js を使ってカスタマイズビューを作成するカスタマイズを紹介します。
カスタマイズビューでは、レコードの一覧表示や、独自の検索ボックスを使ったインクリメンタルサーチを実現します。

サンプル(データ表示、検索)

実際にいくつかサンプルを作ってみます。
今回は、顧客名簿を Vue.js を使って表示するのと、検索まで実装してみたいと思います。

下準備

次のアプリを作って、サンプルデータを入れておいてください。

フィールド名 フィールドコード
顧客名 companyName
顧客電話番号 tel

Cybozu CDN

Cybozu CDN から vue.js の URL をコピーします。

https://js.cybozu.com/vuejs/v3.4.20/vue.global.prod.js
今回はバージョン 3.4.20 を使用します。

Vue.js の簡単な使い方

まず、kintone のデータは使わず、とりあえず kintone 上で Vue.js を使ってみましょう。

カスタマイズビューの作成

顧客企業名と、電話番号を表示するカスタマイズビューを作成してみます。
カスタマイズビューの作り方は次の記事を確認ください。
第 7 回 カスタマイズビューを利用してみよう

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div id="app">
  <table border="1px">
    <tr>
      <th>顧客名</th><th>顧客電話番号</th>
    </tr>
    <tr v-for="customer in customers">
      <td>{{customer.companyName}}</td><td>{{customer.tel}}</td>
    </tr> 
  </table>
</div>

v-for と記述されたところと、二重の波括弧 {{}} でくくられた部分が Vue.js で利用される部分です。

JavaScript カスタマイズ

次の JavaScript ファイルを作成し、kintone にアップロードしましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * kintone x Vuejs
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
(function() {
  'use strict';
  const {createApp} = Vue;
  const customers = [
    {companyName: '株式会社A', tel: '0123-45-6789'},
    {companyName: '株式会社B', tel: '1123-45-6789'},
    {companyName: '株式会社C', tel: '2123-45-6789'},
    {companyName: '株式会社D', tel: '3123-45-6789'},
  ];
  const app = createApp({
    setup() {
      return {
        customers,
      };
    },
  });

  kintone.events.on('app.record.index.show', (event) => {
    if (event.viewId !== 5118521) return event; // 作成したカスタマイズビューのIDを指定
    // 作成されたアプリケーションインスタンスをカスタマイズビューで用意した #app にマウント
    app.mount('#app');

    return event;
  });
})();

次のように表示されます。

kintone のデータを読み込ませる

上記のカスタマイズビューと JavaScript を再度編集して、今度は kintone のレコードを表示させてみましょう。

カスタマイズビュー
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div id="app">
  <table border="1px">
   <tr>
     <th>顧客名</th><th>顧客電話番号</th>
   </tr>
   <tr v-for="record in records">
     <td>{{record.companyName.value}}</td><td>{{record.tel.value}}</td>
   </tr> 
  </table>
</div>
JavaScript カスタマイズ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * kintone x Vuejs
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
(function() {
  'use strict';
  const {createApp, ref} = Vue;

  const app = createApp({
    setup() {
      const records = ref([]);

      function setRecords(newRecords) {
        records.value = newRecords;
      }

      return {
        records,
        setRecords,
      };
    },
  });

  kintone.events.on('app.record.index.show', (event) => {
    if (event.viewId !== 5118521) return event; // 作成したカスタマイズビューのIDを指定
    // 作成されたアプリケーションインスタンスをカスタマイズビューで用意した #app にマウント
    const instance = app.mount('#app');

    instance.setRecords(event.records); // kintoneのrecords配列をそのまま利用
    return event;
  });
})();

ref() 関数を使用した変数はリアクティブな状態となり、変数の値に変更があると Vue が自動的に変更を検出し DOM を更新します。
今回の場合、records という変数がリアクティブな状態になっているため、records が更新されると HTML 側でこの変数を使っている箇所が自動的に更新されます。
また、 records 変数に値をセットするためのメソッド setRecords() を用意し、 event.records の配列をそのまま引数に渡しています。

独自の検索フォームをつけてみましょう。
簡単にインクリメンタルサーチが実装できます。
カスタマイズビュー側に検索用の input 要素を追加し、JavaScript 側にフィルターするための関数を定義します。

カスタマイズビュー
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<div id="app">
  検索 <input type="text" v-model="searchText" placeholder="検索する">
  <table border="1px">
    <tr>
      <th>顧客名</th>
      <th>顧客電話番号</th>
    </tr>
    <tr v-for="record in filteredRecords">
      <td>{{record.companyName.value}}</td>
      <td>{{record.tel.value}}</td>
    </tr> 
  </table>
</div>
JavaScript カスタマイズ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * kintone x Vuejs
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
(function() {
  'use strict';
  const {createApp, ref, computed} = Vue;

  const app = createApp({
    setup() {
      const records = ref([]);
      const searchText = ref(''); // 検索用のデータ追加

      function setRecords(newRecords) {
        records.value = newRecords;
      }

      const filteredRecords = computed(() => {
        return records.value.filter(
          (record) => record.companyName.value.indexOf(searchText.value) !== -1
        );
      });

      return {
        records,
        filteredRecords,
        setRecords,
        searchText,
      };
    },
  });

  kintone.events.on('app.record.index.show', (event) => {
    if (event.viewId !== 5520283) return event; // 作成したカスタマイズビューのIDを指定
    // 作成されたアプリケーションインスタンスをカスタマイズビューで用意した #app にマウント
    const instance = app.mount('#app');

    instance.setRecords(event.records);
    return event;
  });
})();

computed() 関数を使用して宣言した変数 filteredRecords 算出プロパティ (External link) と呼ばれます。
Vue は computed() に渡した関数内で使用されているリアクティブな値を追跡し、リアクティブな値に変更があると算出プロパティも自動的に更新します。
今回の場合、searchText に変更があると自動的に算出プロパティ filteredRecords も更新されます。
また、カスタマイズビュー側でも filteredRecords を使うことでフィルターされた結果をカスタマイズビューに表示できます。

kintone の検索 (External link) の弱点として、一文字での検索ができません。
また、英数字は単語単位でしか検索できないなどの制限がありますが、このインクリメンタルサーチを応用すれば、それらの弱点も克服できます。

おわりに

これだけ簡単に、独自のカスタマイズビューを作ることができるのは魅力的ですよね。
他にも、独自のフォームを作ったり、レコード詳細画面でスペースフォームと活用して表示をカスタマイズしたりできます。
フルスクラッチで書いたり、jQuery 単体でやるよりは楽にできると思います。

さらに 算出プロパティ (External link) コンポーネント (External link) などの機能も使いこなすと kintone でやりにくい、かゆいところまで手が届きます。
学習コストも比較的低いので、ぜひためしてみてください。