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でやりにくい、かゆいところまで手が届きます。
学習コストも比較的低いので、ぜひためしてみてください。