new Vue({
el: "#app",
data: () => ({
ctx: undefined,
draw(begin, end, stroke = 'black', width = 1) {
if (!this.ctx) {
const canvas = this.$refs['canvas'];
if (!canvas?.getContext) return;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
this.ctx = canvas.getContext('2d');
}
if (stroke) {
this.ctx.strokeStyle = stroke;
}
if (width) {
this.ctx.lineWidth = width;
}
this.ctx.beginPath();
this.ctx.moveTo(...begin);
this.ctx.lineTo(...end);
this.ctx.stroke();
},
onToggleCheckbox(group) {
const planeEl = this.$refs['plane'];
const planeRect = planeEl.getBoundingClientRect();
const fromEl = this.$refs['checkbox_' + group.name];
const fromRect = fromEl.getBoundingClientRect();
const from = {
x: fromRect.right - planeRect.left,
y: fromRect.top + fromRect.height / 2 - planeRect.top,
};
group.statuses.forEach((status) => {
const toEl = this.$refs['status_' + status];
const toRect = toEl.getBoundingClientRect();
const to = {
x: toRect.left - planeRect.left,
y: toRect.top + toRect.height / 3 - planeRect.top,
};
console.log(planeRect, from, to);
this.draw(
[from.x, from.y],
[to.x, to.y],
group.checked ? 'white' : 'black',
group.checked ? 4 : 2
);
});
},
questions: [
{
name: 'foo',
checked: false,
statuses: ['ok', 'notok', 'medium'],
},
{
name: 'bar',
checked: false,
statuses: ['ok', 'notok'],
},
{
name: 'baz',
checked: false,
statuses: ['ok'],
},
{
name: 'oo',
checked: false,
statuses: ['ok', 'notok', 'medium'],
},
],
statuses: [
{
name: 'a',
checked: false,
statuses: ['notok', 'medium'],
},
{
name: 'b',
checked: false,
statuses: ['medium', 'ok', 'notok'],
},
{
name: 'c',
checked: false,
statuses: ['ok', 'notok'],
},
{
name: 'd',
checked: false,
statuses: ['ok', 'notok'],
},
],
}),
};
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="demo" :ref="'plane'">
<canvas :ref="'canvas'"></canvas>
<div class="questions">
<div
v-for="(group, index) in questions"
:key="'question_' + index"
:group="group"
>
<input
type="checkbox"
v-on:click="() => onToggleCheckbox(group)"
v-model="group.checked"
:ref="'checkbox_' + group.name"
/>
<span>{{ group.name }}</span>
</div>
</div>
<div class="statuses">
<div
v-for="(status, index) in statuses"
:key="'question_' + index"
:group="status"
>
<span>{{ status.name }}</span>
<input type="checkbox" :ref="'status_' + status.name" />
</div>
</div>
</div>
Code link:- https://stackblitz.com/edit/vue-raumkh?file=src%2FApp.vue
Error:- Cannot read properties of undefined (reading ‘getBoundingClientRect’)
I am using two v-for, one on left side content and one on right side content.
and preforming some functionality like, When user click on checkbox on left hand side
I am able to draw line using canvas, by setting width and height of the lines. and targeting the right hand side status.
But the problem is in my v-for, Where when i clicked on the checkbox i am getting the error. That i did not set the property correctly.