Home > Back-end >  Error with a Vue.js "calc(...)" attribute binding
Error with a Vue.js "calc(...)" attribute binding

Time:11-18

I want to draw a line in an SVG. This line must be vertical and its length must correspond to the height of the SVG that contains it. As the SVG is responsive I can't use pixel coordinates. Instead I put a rect of width 1px and height 100%. The problem is that when I try to position it on the x axis in relation to a reference, Vue.js gives me an error, (even though it works: the result)

Error: Invalid value for <rect> attribute x="calc( 100% / 5 * 2 )"

The problem comes from:

:x="'calc( 100% / '   props.max   ' * '   props.x   ' )'"

Code

<script setup lang="ts">
import { defineProps } from "vue";

const props = defineProps<{
  x: number,
  max: number
}>();
</script>

<template>
  <rect :x="'calc( 100% / '   props.max   ' * '   props.x   ' )'" />
</template>

<style scoped>
rect {
  width: 1px;
  height: 100%;
  stroke: none;
  fill: #000000;
}
</style>

I also tried

<script setup lang="ts">
import { defineProps, Ref, ref, onMounted } from "vue";

const props = defineProps<{
  x: number,
  max: number
}>();

const vertical_line: Ref<HTMLElement | null> = ref(null);

onMounted(() => {
  vertical_line.value?.focus();
  if (vertical_line.value !== null && typeof vertical_line.value === "object" &&
      "setAttribute" in vertical_line.value)
    vertical_line.value
        .setAttribute("x", "calc( 100% / "   props.max   " * "   props.x   " )");
});
</script>

<template>
  <rect ref="vertical_line" />
</template>

<style scoped>
rect {
  width: 1px;
  height: 100%;
  stroke: none;
  fill: #000000;
}
</style>

CodePudding user response:

Looks like your code works, maybe wrong props?

const { ref } = Vue
const app = Vue.createApp({
  setup() {
    const x = ref(6)
    const max = ref(30)
    return { x, max }
  }
})
app.component('lineI', {
  template: `
    <rect :x="'calc( 100% / '   max   ' * '   x   ' )'" />
  `,
  props: {
    x: { type: Number },
    max: { type: Number }
  },
})
app.mount('#demo')
rect {
  width: 1px;
  height: 100%;
  stroke: none;
  fill: #000000;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  <svg>
    <line-i :x="x" :max="max"></line-i>
  </svg>
  <br>
  <input type="number" v-model="x" />
  <input type="number" v-model="max" />
</div>

  • Related