How to access an HTML ref in VueJS 3 and Typescript with Vue Class Component?
Asked Answered
D

1

7

I'm banging my head on the following problem: I created a QRCode component using Vue 3 and Typescript with the following code:

<template>
  <canvas ref="qrcodeVue"> </canvas>
</template>

<script lang="ts">
import QRCode from "qrcode";
import { Vue, Options } from "vue-class-component";
import { ref } from "vue";

@Options({
  props: {
    value: {
      type: String,
      required: true
    },
    size: {
      type: [Number, String],
      validator: (s: [number | string]) => isNaN(Number(s)) !== true
    },
    level: {
      type: String,
      validator: (l: string) => ["L", "Q", "M", "H"].indexOf(l) > -1
    },
    background: String,
    foreground: String
  }
})
export default class QRCodeVue extends Vue {
  value = "";
  size: number | string = 100;
  level: "L" | "Q" | "M" | "H" = "L";
  background = "#ffffff";
  foreground = "#0000ff";

  mounted() {
    const _size = Number(this.size);
    const scale = window.devicePixelRatio || 1;
    const qrcodeVue = ref<HTMLCanvasElement | null>(null);

    QRCode.toCanvas(qrcodeVue, this.value, {
      scale: scale,
      width: _size,
      color: { dark: this.foreground, light: this.background },
      errorCorrectionLevel: this.level
    });
  }
}
</script>

But qrcodeVue is always referring to nothing, I never get access to the canvas itself. What am I missing? Where should I put this ref() code? I also tried with defineComponent with the same result. Thanks for any clue.

(BTW, I also tried to use the npm qrcode-vue package but it doesn't seem to support Vue 3)

Dianetics answered 28/12, 2020 at 19:43 Comment(2)
I think you might be missing the .value part of qrcodeVue to access the canvas element QRCode.toCanvas(qrcodeVue.value, this.value, ...).Interpretative
Thanks Ibrahim. See Dan's answer below for the real thing.Dianetics
E
7

You have to declare the ref qrcodeVue as a class property first, and not inside mounted.

Only then will it be be available and populated with the ref element in mounted:

export default class QRCodeVue extends Vue {
  qrcodeVue = ref<HTMLCanvasElement | null>(null); // not inside mounted

  mounted() {
    console.log(this.qrcodeVue);  // now it's available
  }
}

This is the equivalent to the following Vue 3 setup syntax:

setup() {
  const qrcodeVue = ref(null);
  onMounted(() => {
    console.log(qrcodeVue.value);
  })
  return {
    qrcodeVue
  }
}
Eddi answered 29/12, 2020 at 5:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.