カテゴリー
コンピューター

Vue.js 3 で flatpickr をラップした SFCその2 。ページ移動時に発生していたエラーを解消する

ページ移動時に発生していたエラー内容

Vue Router のリンクをクリックすると、次のエラーが発生していました。

Uncaught (in promise) TypeError: flatpickr__WEBPACK_IMPORTED_MODULE_1__.default.destroy is not a function
    at app.js:17969
    at callWithErrorHandling (app.js:6469)
    at callWithAsyncErrorHandling (app.js:6478)
    at Array.hook.__weh.hook.__weh (app.js:9214)
    at flushPostFlushCbs (app.js:6669)
    at flushJobs (app.js:6705)

完成したコード全体

flatpickr をラップした SFC 、laravel/resources/js/components/BaseFlatpickr.vue です。

<template>
  <input ref="root" type="text" @input="updateModelValue" />
</template>

<script>
import { ref, onMounted, onUnmounted } from "vue";
import flatpickr from "flatpickr";
import { Japanese } from "flatpickr/dist/l10n/ja.js";

export default {
  name: "BaseFlatpickr",
  props: {
    config: {
      default: () => {},
      required: false,
      type: Object,
    },
    modelValue: {
      default: null,
      required: true,
      type: String,
    },
  },
  emits: ["update:modelValue"],
  setup(props, { emit }) {
    const root = ref(null);
    let fp = null;

    const updateModelValue = (event) => {
      emit("update:modelValue", event.target.value);
    };

    onMounted(() => {
      Japanese.firstDayOfWeek = 1;
      const config = {
        locale: Japanese,
        ...props.config,
      };
      fp = flatpickr(root.value, config);
    });

    onUnmounted(() => {
      fp.destroy();
    });

    return { root, updateModelValue };
  },
};
</script>

flatpickr をラップした SFC を利用するコンポーネント、laravel/resources/js/views/SampleFlatpickr.vue です。

  • Vue Router で別ページへ移動するリンクをもうけた点のみ、 前回 と異なる。
<template>
  <div class="container">
    <h1>SampleFlatpickr</h1>
    <base-flatpickr v-model="date1" />
    <base-flatpickr v-model="date2" />

    <router-link :to="{ name: 'SampleDropzone' }">SampleDropzone</router-link>
  </div>
</template>

<script>
import BaseFlatpickr from "../components/BaseFlatpickr.vue";
import { ref } from "vue";

export default {
  name: "SampleFlatpickr",
  components: { BaseFlatpickr },
  setup() {
    return {
      date1: ref(""),
      date2: ref(""),
    };
  },
};
</script>

ページ移動時に発生していたエラーをの原因と解決方法

onUnmounted の処理を間違えていたようです。そこで、 onMounted 時に flatpickr をインスタンス化した際に変数へと入れておき、 onUnmounted 時にはこのインスタンスから destroy を呼ぶようにしました。次が変更点です。

$ git diff laravel/resources/js/components/BaseFlatpickr.vue
diff --git a/laravel/resources/js/components/BaseFlatpickr.vue b/laravel/resources/js/components/BaseFlatpickr.vue
index e2c6924..1f6672d 100644
--- a/laravel/resources/js/components/BaseFlatpickr.vue
+++ b/laravel/resources/js/components/BaseFlatpickr.vue
@@ -24,6 +24,7 @@ export default {
   emits: ["update:modelValue"],
   setup(props, { emit }) {
     const root = ref(null);
+    let fp = null;

     const updateModelValue = (event) => {
       emit("update:modelValue", event.target.value);
@@ -35,11 +36,11 @@ export default {
         locale: Japanese,
         ...props.config,
       };
-      flatpickr(root.value, config);
+      fp = flatpickr(root.value, config);
     });

     onUnmounted(() => {
-      flatpickr.destroy();
+      fp.destroy();
     });

     return { root, updateModelValue };
$

おわりに

今回は、 Laravel 6 の Vue.js 3 で、デイトピッカー flatpickr のラッパーシングルファイルコンポーネント (SFC) を作った – oki2a24 の続きとなります。まだ、 props がマウント後に変更された場合の処理など、改善点が思いつきます。けれども、今のところはこれで充分ですので、必要となりましたら、改善していきたいと思います。

以上です。

コメントを残す