🥦

kintoneアプリの一覧画面をVue3+Vuetify3を使って表示

2025/01/22に公開

前回に引き続き、今度はVue3+Vuetify3を使ってkintoneの一覧画面を表示したいと思います。

Vuetify3のロードマップをみるとまだまだ開発中という感じですが、Vue2+Vuetify2もサポート終了なので、ああでもないこうでもないと試行錯誤しながらようやく出来上がりました。

こちらもぜひご利用ください!

1. 利用環境

以下の環境で動作しています。

  • kintone … クラウド最新版(2025年1月時点)
  • Vue2 … バージョン3.5.13
  • Vuetify2 … バージョン3.7.7

2. 用意するもの

2-1. 一覧画面を作成

アプリ管理 → 一覧 → 「+」マーク から、新しい一覧をカスタマイズ形式で作成します。
本記事では以下のように設定します。

一覧名 レコード一覧の表示形式 一覧を表示する範囲 ページネーションを表示する
Vue3+Vuetify3一覧 カスタマイズ PC版のみで表示する チェックオフ

2-2. テストデータ

テストデータはこんな感じです。
テストデータ

3. スクリプト全体

一覧に設定するHTMLと、JavaScript/CSSカスタマイズに設置するスクリプトを記載します。

3-1. HTML

「テスト一覧」のHTML部分
<div id="kintone-vue3-app">
  <v-app>
    <v-main>
      <v-container fluid>
        <v-row class="bg-deep-purple-lighten-5">
          <v-col class="ma-2" cols="12">
            <v-data-table
              :headers="headers"
              :items="userList"
              :loading="isLoading"
            ></v-data-table>
          </v-col>
          </v-row>
      </v-container>
    </v-main>
  </v-app>
</div>

さきほど作成した「Vue3+Vuetify3一覧」のHTMLフィールドに本内容をコピペ。
コンポーネントを識別しやすいように、

  • v-rowの属性にclass="bg-deep-purple-lighten-5"を追加して背景色を薄紫色に
  • v-colの属性にclass="ma-2"を追加してマージンを設定

と、Vue2+Vuetify2のときと同じ装飾を加えています。
記法に若干の違いがあるので記載しておくと、色の指定は以下のように変更になりました。

-        <v-row class="deep-purple lighten-5">
+        <v-row class="bg-deep-purple-lighten-5">

3-2. JavaScript

次に「customizeView.js」という名称で以下の内容を保存します。

customizeView.js
((Vue,Vuetify) => {
  
  const events = {
    show: [
      'app.record.detail.show',
      'mobile.app.record.detail.show',
    ],
    index: [
      'app.record.index.show',
      'mobile.app.record.index.show',
    ]
  }

  let vObj = null;

  async function getRecords(appId) {
    const client = new KintoneRestAPIClient();
    const params = {
      app: appId,
    }
    return await client.record.getAllRecords(params).then((resp) => {
      return resp.map((row) => {
        row.hogehoge = 'テストデータですよー!'
        return row
      });
    })
  }

  function generateView() {
    const vObj = Vue.createApp({
      data() {
        const columnList = [
          {
            title: 'ユーザー名', //表示名
            key: 'userName.value', //kintoneアプリのどの項目を表示するか
            sortable: true, //列タイトルクリックしたときにソートできるかどうか
          },
          {title: 'ユーザーID', key: 'userID.value'},
          {title: 'メールアドレス', key: 'mailAddress.value'},
          {title: '生年月日', key: 'birthday.value'},
          {title: 'ふがふが', key: 'hogehoge'},
        ]

        const users = Vue.ref([]);
        function addUser(value) {
          users.value.push(value)
        }
        function addUsers(value) {
          users.value = value
        }

        const loadingValue = Vue.ref(true);
        function changeLoadingState(value) {
          loadingValue.value = value
        }

        return {
          columns: columnList,

          userList: users,
          addUser,
          addUsers,

          isLoading: loadingValue,
          changeLoadingState,
        }
      },

    }).use(
      Vuetify.createVuetify({
        icons: {
          iconfont: 'mdi',
        },
      })
    )
    
    return vObj.mount('#kintone-vue3-app')
  }

  kintone.events.on(events.index, async function(event) {
    if (event.viewType!=='custom' || event.viewId!==5536090) {return event;};

    const appId = event.appId

    vObj = generateView()
    await getRecords(appId).then((resp) => {
      vObj.addUsers(resp)
    });
    vObj.changeLoadingState(false);

    return event;
  });

})(Vue,Vuetify);

4. 説明

4-1. スクリプトを動作させる一覧画面を指定する

part of customizeView.js
    if (event.viewType!=='custom' || event.viewId!==5536090) {return event;};

アプリ内のいろんなページで動作してもらっては困るので、しょっぱなで一覧IDを指定しておきます。
この箇所にあるevent.viewIdは環境ごとにかわりますので、5536090の箇所を、前段階で作成した一覧画面に記載の一覧IDに書き換えてください!

4-2. Vueオブジェクト生成時のポイント

data() {}内に設定しているレコード一覧userList等をref()でラップして設定

part of customizeView.js
      data() {
        const users = Vue.ref([]);
        function addUser(value) {
          users.value.push(value)
        }
        function addUsers(value) {
          users.value = value
        }

        const loadingValue = Vue.ref(true);
        function changeLoadingState(value) {
          loadingValue.value = value
        }

        return {
          columns: columnList,

          userList: users,
          addUser,
          addUsers,

          isLoading: loadingValue,
          changeLoadingState,
        }
      },

<v-data-table>のデータ本体としたいuserListは初期段階で空配列としています。
対象データが大量な場合は表示までにレスポンスがなく、ユーザビリティが低下するのを防ぐ狙いがあります。
BooleanのisLoadingを用意してロード中という事を伝えているのも同じ理由です。

なお
 userListはHTML内の:items="userList"と、
 isLoadingはHTML内の:loading="isLoading"と、
それぞれ関連付けています。


vue3ではcomposition APIという仕組みが使えるようになっていて、

part of customizeView.js
        const users = Vue.ref([]);
        function addUser(value) {
          users.value.push(value)
        }
        function addUsers(value) {
          users.value = value
        }

といった、"値"と、"それに対して行いたい処理" をまとめた記述ができというのが大きなメリットになっています。
vue2ではmethods内やcomputed内に分散させなければならなかったので助かります。
現在はパッと見で全容を把握・整理できる分量の開発しかしていないのでメリットを感じづらいですが、大規模な開発になるにつれこのメリットが活きてくるのではと思います。

タイトル行を設定

part of customizeView.js
      data() {
        const columnList = [
          {
            title: 'ユーザー名', //表示名
            key: 'userName.value', //kintoneアプリのどの項目を表示するか
            sortable: true, //列タイトルクリックしたときにソートできるかどうか
          },
          {title: 'ユーザーID', key: 'userID.value'},
          {title: 'メールアドレス', key: 'mailAddress.value'},
          {title: '生年月日', key: 'birthday.value'},
          {title: 'ふがふが', key: 'hogehoge'},
        ]
        // ~
        return {
          columns: columnList,
        }
      }

columnsを用意し、<v-data-table>のタイトル行として設定します。
HTML内の:headers="columns"でこのオブジェクトと関連付けています。
なおVue2からの変化はこんな感じです↓

part of customizeView.js
-            {text: 'ユーザーID', value: 'userID.value'},
+            {title: 'ユーザーID', key: 'userID.value'},

表示名はtextからtitleに変更、内部値はvalueからkeyに変更になっています。

keyに記述する内容は、kintoneのフィールドコード+「.value」といつも使っている形式で変更なし、getRecords()した内容をそのまま使うわけではない場合は、最後の「ふがふが」列のようになります。

肝心のVuetifyを、プラグインとして使うよう設定

part of customizeView.js
    .use(
      Vuetify.createVuetify({
        icons: {
          iconfont: 'mdi',
        },
      })
    )

Vue2+Vuetify2のパターンから変化のあった箇所です。
Vue2ではVueオブジェクトの一データとして生成していましたが、Vue3ではuse()を使ってプラグイン追加します。
前回と同様アイコンを使うときに備えてicons: {iconfont: 'mdi'}を指定しています。

マウント

part of customizeView.js
    return vObj.mount('#kintone-vue3-app')

ここもVue2+Vuetify2のパターンから変化がありました。
微妙な違いですが、.$mount()から.mount()になっています。これでHTMLの指定idとの紐づけも完了!

↑ここまでの処理が一通り終わったら…

part of customizeView.js
    await getRecords(appId).then((resp) => {
      vObj.addUsers(resp)
    });
    vObj.changeLoadingState(false);

最後にレコード取得&設定と、ローディングバー非表示して完了です。
それぞれsetup()内で作成したaddUsers()changeLoadingState()を介して、リアクティブなオブジェクトの値を更新しています。

5. アプリにライブラリ等を反映

アプリ管理 → 設定 → カスタマイズ/サービス連携 → JavaScript/CSSでカスタマイズ
の中に、上から順に以下内容を追加します。

全て指定できたら「保存」→「アプリを更新」します。

6. 完成

ここまでのステップが終了すると、こんな感じになります↓

7. さいごに

Vue3+Vuetify3もこれでようやく、カスタマイズのための足掛かりができました!
Vue2+Vuetify2がサポート切れるのは残念ですが、これで何とか開発効率化につなげられたらなあと思う次第です。

Discussion