Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

LorienDarenya's avatar

Check checkboxes using database information and Vue?

Alright, here we go!

I am developing a site with Vue and Laravel. I'm very new to Vue and am self-taught. I am looking for help with the following scenario:

Markings are associated with specific colors via a color_marking table. When querying the database while an edit form is active, I am retrieving the marking itself, as an Array in the Vue props section of my component, and the marking colors associated with it as a relationship using with(). It looks like this:

$marking = Marking::with('colors')->find(1);

I know, of course, how to retrieve the colors while in a Laravel blade file. However, these colors have to change dynamically based on the marking type and be checked at the outset if they are part of the relationship. My Vue looks similar to this (shortened for the sake of the reader's sanity):

<template>
<div>
<div v-for="(color, index) in colors" :key="index">
<label>
<input type="checkbox" :value="{{ color.id }}" v-model="markingColors" />
{{ color.name }}
</label>
</div>
</template>
<script>
import MarkingApi from "../apis/MarkingApi.js";

export default {
    name: 'marking-edit',
    props: {
        marking: {
            type: Object,
            required: true
        }
    },
data: {
markingColors: this.marking.colors;
selectedMarkingColors: [],
}
}
}
</script>

Now, I'm looking for the following to happen:

The marking data is pulled up in the form. This happens just find with my extended code. The marking colors (all possible ones), are pulled from the database and listed. Again, no problem here. The marking colors are checked based on this.marking.colors (my relationship). This does not happen unless I specify the marking colors in an array like [40, 41, 42]. I know from endless tinkering that the this.marking.colors is being returned as an object.

How in the world can I ensure that the selected marking colors are checked upon render, however?

Thank you so much!

0 likes
19 replies
kiri1101's avatar

@loriendarenya You call an array colors in your v-for but don't seem to define it. Maybe looping through markingColors in place of colors was what you intended doing

LorienDarenya's avatar

@kiri1101 Thank you so much for your response. I shortened the Vue a great deal and will note that I call the colors using async and have no problem getting that data in the template. It's a post call to a route which pulls the colors on load. <3

kiri1101's avatar

@LorienDarenya My bad then, I read through again and from the result you get while using [40,41,42], I conclude markingColors might be an Object reason why you do not get thesame result like with [40,41,42].

So make sure you're calling the right key from markingColors or extract the values you need from markingColors into a new array and use

LorienDarenya's avatar

@kiri1101 I'm honestly uncertain how to get the data I need. this.marking.colors does indeed return an object, hince my issue, as you observed.

Ben Taylor's avatar
Level 35

I would personally make markingColors into an array of objects that looked something like this:

{
	id: { the color id},
	name: { the color name},
	selected: { set this to true or false at the start depending if the color id is in this.marking.colors }
}

You would set this when you load colors. Have it as an empty array to begin. It's a little hard to tell you specifically how to do that since I have no idea what this.marking.colors returns. I'm assuming its an array of objects?

So maybe something like this.

this.markingColors = colors.map(color => ({
		id: color.id,
		name: color.name,
		selected: this.marking.colors.some(mc => mc.id === color.id)
}))

Then in your checkbox loop, i'd change it to something more like this:

<div v-for="(color) in markingColors" :key="color.id">
<label>
<input type="checkbox"  v-model="color.selected" />
{{ color.name }}
</label>
</div>

You can then get rid of selectedMarkingColors from data, or make it into a computed property that returns markingColors filtered by the selected property.

computed: {
	selectedMarkingColors() {
		return this.markingColors.filter(c => c.selected)	
	}
}
LorienDarenya's avatar

@Ben Taylor Thank you so much for your reply! I feel like I'm missing a step. this.marking.colors are all colors currently associated with the marking, while colors is just a list of all available colors based on marking type. Both are drawn from the DB, so I'm stumbling a bit on how to convert them to what I need.

LorienDarenya's avatar

@Ben Taylor My screenreader neglected to tell me some of the code. I apologize, I am integrating it all in full now. <3

LorienDarenya's avatar

@Ben Taylor I hate to be a bother, but I'm getting a syntax error when doing the .map(), even when copying and pasting directly from the post. <3 Thank you!

LorienDarenya's avatar

@Ben Taylor Still working through, but resolved the syntax issue, it was on my part.

LorienDarenya's avatar

Okay, I'm not sure I have this where it need to go, so I have pasted my async showColors method:

        async showColors() {
            try {
                const { data } = await MarkingApi.colors(this.$data);
this.showMarkingColors = true;
this.colors = data.map(color => ({
		id: color.id,
		name: color.name,
		selected: this.marking.colors.some(mc => mc.id === color.id)
}));
                        } catch (error) {
                //alert(JSON.parse(error.request.response).message);
                console.log(error);
            }
},
LorienDarenya's avatar

@Ben Taylor Almost. I need to figure out where to first populate the colors when the page first loads. I think it's the mounted() area, though. Thank you so much for both your response and your help in this fiasco. <3

LorienDarenya's avatar

@Ben Taylor One more thing, it's not picking up the checkboxes for the markingColors data property. I'm not sure why or how to fix this honestly, but I'm pushing onward.

LorienDarenya's avatar

@Ben Taylor I thought it might be helpful (I apologize to your sanity) to post the entirity of my .vue file. Here we go, please be gentle. <3

<template>
<div v-if="success" class="alert alert-success" role="alert">
{{ success }}
</div>
<div v-else>
<div v-if="errors" class="alert alert-danger" role="alert">
    <div v-for="(v, k) in errors" :key="k">
        <p v-for="error in v" :key="error">
        {{ error }}
        </p>
    </div>
</div>
<p>Use the form below to edit an existing marking.</p>
<form @submit.enter.prevent="edit" id="marking-edit" method="post" role="form">
<div>
<label for="poseId">
	Pose:
</label>
		<select name="poseId" id="poseId" v-model="poseId" required>
<option value="" selected disabled>Choose a pose</option>
<option v-for="pose in poses" :key="pose.id" :value="pose.id">
{{ pose.friendly_name }}
</option>
</select>
</div>
	<div>
		<label for="type">
			Type:
		</label>
		<select name="type" id="type" v-model="type" @change="showColors" required>
<option value="" selected disabled>Choose a type</option>
			<option value="light">Light Marking</option>
			<option value="dark">Dark Marking</option>
		</select>
	</div>
	<div>
		<label for="name">
			Name:
		</label>
		<input type="text" name="name" id="name" v-model="name" required />
	</div>
<div>
<label for="markingColors">
Marking Colors:
</label>
<div v-for="color in colors" :key="color.id">
<label>
<input type="checkbox" name="markingColors[]" :key="color.id" :value="color.id" :id="'markingColors'+color.id" v-model="color.selected" />
{{ color.name }}
</label>
</div>
</div>
	<div>
		<label>
			<input type="checkbox" name="special" value="1" id="special" v-model="special" true-value="1" false-value="0" />
			Special?
		</label>
		</div>
	<div>
		<label>
			<input type="checkbox" name="public" value="1" id="public" v-model="public" true-value="1" false-value="0"  />
Public?
</label>
		</div>
<div>
<button type="submit" name="edit" id="edit">
Edit
</button>
</div>
</form>
</div>
</template>

<script>
import MarkingApi from "../apis/MarkingApi.js";

export default {
    name: 'marking-edit',
    props: {
        poses: {
            type: Array,
            required: true
        },
        marking: {
            type: Object,
            required: true
        }
    },
mounted() {
this.colors = this.showColors();
},
computed: {
	selectedMarkingColors() {
		return this.markingColors.filter(c => c.selected)	
	}
},
   data() {
        return {
success: "",
errors: {},
            poseId: this.marking.pose_id,
            type: this.marking.type,
name: this.marking.friendly_name,
colors: {},
markingColors: [],
special: this.marking.special,
public: this.marking.public
        }
    },
methods: {
        async showColors() {
            try {
                const { data } = await MarkingApi.colors(this.$data);
this.colors = data.map(color => ({
		id: color.id,
		name: color.friendly_name,
		selected: this.marking.colors.some(mc => mc.id === color.id)
}));
                        } catch (error) {
                //alert(JSON.parse(error.request.response).message);
                console.log(error);
            }
},
        async edit() {
            try {
                const { data } = await MarkingApi.edit(this.marking.id, this.$data);
this.success = 'This marking has been successfully edited.';
                        } catch (error) {
this.success = '';
this.errors = error.response.data.errors;
            }
}
}
}
</script>
LorienDarenya's avatar

FOr reference, I've updated the code a bit, as follows:

I am so close I can taste it! I have added an @click to my checkboxes and linked it to selectedMarkingColors, then echoed it in the template. It works beautifullly, but I am having trouble getting this data to coincide with markingColors, which is the array my form looks for to sync to the database. Thank you so much everyone thus far!

LorienDarenya's avatar

Any thoughts? I am still stuck on converting the selectedMarkingColors to markingColors for the form to accept it.

Ben Taylor's avatar

Try this

<template>
<div v-if="success" class="alert alert-success" role="alert">
{{ success }}
</div>
<div v-else>
<div v-if="errors" class="alert alert-danger" role="alert">
    <div v-for="(v, k) in errors" :key="k">
        <p v-for="error in v" :key="error">
        {{ error }}
        </p>
    </div>
</div>
<p>Use the form below to edit an existing marking.</p>
<form @submit.enter.prevent="edit" id="marking-edit" method="post" role="form">
<div>
<label for="poseId">
	Pose:
</label>
		<select name="poseId" id="poseId" v-model="poseId" required>
<option value="" selected disabled>Choose a pose</option>
<option v-for="pose in poses" :key="pose.id" :value="pose.id">
{{ pose.friendly_name }}
</option>
</select>
</div>
	<div>
		<label for="type">
			Type:
		</label>
		<select name="type" id="type" v-model="type" @change="showColors" required>
<option value="" selected disabled>Choose a type</option>
			<option value="light">Light Marking</option>
			<option value="dark">Dark Marking</option>
		</select>
	</div>
	<div>
		<label for="name">
			Name:
		</label>
		<input type="text" name="name" id="name" v-model="name" required />
	</div>
<div>
<label for="markingColors">
Marking Colors:
</label>
<div v-for="color in colors" :key="color.id">
<label>
<input type="checkbox" :id="'markingColors'+color.id" v-model="color.selected" />
{{ color.name }}
</label>
</div>
</div>
	<div>
		<label>
			<input type="checkbox" name="special" value="1" id="special" v-model="special" true-value="1" false-value="0" />
			Special?
		</label>
		</div>
	<div>
		<label>
			<input type="checkbox" name="public" value="1" id="public" v-model="public" true-value="1" false-value="0"  />
Public?
</label>
		</div>
<div>
<button type="submit" name="edit" id="edit">
Edit
</button>
</div>
</form>
</div>
</template>

<script>
import MarkingApi from "../apis/MarkingApi.js";

export default {
    name: 'marking-edit',
    props: {
        poses: {
            type: Array,
            required: true
        },
        marking: {
            type: Object,
            required: true
        }
    },
mounted() {
this.showColors();
},
computed: {
	selectedMarkingColors() {
		return this.markingColors.filter(c => c.selected)	
	}
},
   data() {
        return {
success: "",
errors: {},
            poseId: this.marking.pose_id,
            type: this.marking.type,
name: this.marking.friendly_name,
colors: [],
special: this.marking.special,
public: this.marking.public
        }
    },
methods: {
        async showColors() {
            try {
                const { data } = await MarkingApi.colors(this.$data);
this.colors = data.map(color => ({
		id: color.id,
		name: color.friendly_name,
		selected: this.marking.colors.some(mc => mc.id === color.id)
}));
                        } catch (error) {
                //alert(JSON.parse(error.request.response).message);
                console.log(error);
            }
},
        async edit() {
            try {
                const { data } = await MarkingApi.edit(this.marking.id, {
	name: this.name,
	markingColors: this.selectedMarkingColors.map(c => c.id), // Assuming you just want the id?
	special: this.special,
	public:  this.public
});
this.success = 'This marking has been successfully edited.';
                        } catch (error) {
this.success = '';
this.errors = error.response.data.errors;
            }
}
}
}
</script>
LorienDarenya's avatar

@Ben Taylor I never even thought of this! I see what you did here, but in practice it seems to be throwing a promise rejection (all my screenreader could get out of the console). Thank you for your help in this matter. <3

LorienDarenya's avatar

@Ben Taylor I fixed it! It works beautfiully! Thank you so much for your help!

Please or to participate in this conversation.