I have this form that i'm building for a CMS website which is displaying some information stored in the database. I want a user to be able to select for example on the buttons section which buttons he wants to use for the post. with the solution i'm trying to use right now,when a user selects one check box , all 4 check boxes are being selected. How do i fix this?
<template>
<form @submit.prevent="submit">
<div>
<div class="mb-3 col-6 mx-auto">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" placeholder="title" v-model="form.title">
</div>
<div class="mb-3 col-6 mx-auto">
<label for="Body" class="form-label">Body</label>
<textarea class="form-control" id="body" rows="3" placeholder="body" v-model="form.body"></textarea>
</div>
<!-- THE SECTION WITH A PROBLEM-->
<div class="mb-3 col-6 mx-auto">
<label for="Body" class="form-label">Buttons</label>
<div class="d-flex flex-wrap">
<div v-for="button in buttons" :key="button.id" class="form-check">
<label class="form-check-label d-flex align-items-center">
<div>
<input class="form-check-input me-2" type="checkbox" :value="button.id" v-model="selectedButtons">
{{ button.buttonTitle }}
</div>
</label>
</div>
</div>
</div>
<div class="mb-3 col-6 mx-auto">
<label for="Body" class="form-label">Images</label>
<div class="d-flex flex-wrap">
<div v-for="upload in uploads" :key="upload.id" class="form-check m-2">
<input class="form-check-input" type="checkbox" :value="upload.id">
<img :src="upload.images" alt="Image" class="img-fluid" style="height: 100px; width: 250px;" />
</div>
</div>
</div>
</div>
<div class="mb-3 col-6 mx-auto">
<div class="d-flex flex-wrap">
<button class="btn btn-dark btn-outline-secondary dropdown-toggle" type="button"
data-bs-toggle="dropdown" aria-expanded="false">Users</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item">
<!-- New line for the Select All checkbox -->
<input type="checkbox" v-model="selectAllChatIds"> Select All
</a>
</li>
<li v-for="chat in props.chatId" :key="chat.id">
<a class="dropdown-item" href="#"><input type="checkbox" :value="chat.chatId"
v-model="selectedChatIds"> {{ chat.chatId
}}</a>
</li>
</ul>
<button class=" btn btn-dark btn-outline-secondary dropdown-toggle" type="button"
data-bs-toggle="dropdown" aria-expanded="false">channels</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item">
<!-- New line for the Select All checkbox -->
<input type="checkbox" v-model="selectAll"> Select All
</a>
</li>
<li v-for="channel in channelId" :key="channel.id"><a class="dropdown-item" href="#"> <input
type="checkbox" :value="channel.channelID" v-model="selectedChannels">{{
channel.channelID
}}</a></li>
</ul>
</div>
</div>
<div class="mb-3 col-6 mx-auto">
<div>
<DateTimePicker />
</div>
<div>
<TimePicker />
</div>
<br>
<div class="d-grid gap-2">
<button class="btn btn-dark" type="submit">send message</button>
</div>
</div>
</form>
</template>
<script setup>
import DateTimePicker from '@/Components/datetimepicker.vue';
import TimePicker from '@/Components/timepicker.vue';
import { ref, watch } from 'vue';
import { useForm } from '@inertiajs/vue3';
const selectedChannels = ref([]);
const selectedChatIds = ref([]);
const selectAll = ref(false);
const selectAllChatIds = ref(false);
const selectedButtons = ref([]);
const props = defineProps({
uploads: Array,
buttons: Array,
chatId: Array,
channelId: Array,
errors: Object
});
const form = useForm({
title:null,
body:null,
chatID:[],
channelID:[],
buttons:[],
images:[],
date:null,
time:null,
});
function submit() {
form.post("/message");
}
watch(selectAll, (newValue) => {
if (newValue) {
selectedChatIds.value = props.chatId.map(chat => chat.chatId);
} else {
selectedChatIds.value = [];
}
});
watch(selectAll, (newValue) => {
if (newValue) {
selectedChannels.value = props.channelId.map(channel => channel.channelID);
} else {
selectedChannels.value = [];
}
});
watch(selectedChannels, () => {
selectAll.value = selectedChannels.value.length === props.channelId.length;
});
watch(selectedChatIds, () => {
selectAllChatIds.value = selectedChatIds.value.length === props.chatId.length;
});
</script>
===============controller================
public function message(request $request)
{
try {
$fields = $request->validate([
'title' => 'required',
'body' => 'required',
'chatID' => 'nullable',
'channelID' => 'nullable',
'buttons' => 'required|array',
'images' => 'nullable',
'date' => 'required',
'time' => 'required',
]);
if ($request->hasFile('sentimages')) {
$fields['images'] = Storage::disk('public')->put('sentimages', $request->images);
}
$fields['buttons'] = json_encode($fields['buttons']);
message::create($fields);
return redirect()->route('CMS')->with('successfully added');
} catch (\Exception $e) {
return redirect()->back()->withErrors(['title'=>'Failed to upload title','body'=>'failed to insert body',
'chatID'=>'failed to insert chatID','channelID'=>'failed to insert channelID',
'buttons'=>'failed to insert buttons','images'=>'failed to insert images','date'=>'failed to add date', 'time'=>'failed to add time']);
}
}
public function telegramCMS()
{
$uploads = uploadImage::all(['images']);
$buttons = TelegramUpload::all(['buttonTitle']);
$chatId = ChatId::all(['chatId']);
$channelId = channelID::all(['channelID']);
foreach ($uploads as $upload) {
$upload->images = asset('storage/' . $upload->images);
}
return inertia::render('Telegram/TelegramBotCMS', [
'uploads' => $uploads,
'buttons' => $buttons,
'chatId' => $chatId,
'channelId' => $channelId
]);
}
========MODELS=======
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class message extends Model
{
use HasFactory;
protected $table = 'messages';
protected $fillable = ['title','body','chatID','channelID','buttons','images','date','time'];
protected $casts = ['chatID'=>'array','buttons'=>'array','channelID'=>'array','images'=>'array'];
}
========= Migration=====================
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('body');
$table->json('buttons');
$table->json('chatID')->nullable();
$table->json('channelID')->nullable();
$table->json('images')->nullable();
$table->time('time');
$table->time('date');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('messages');
}
};
when i click on one check box, all of them are being selected
The main issue is this part v-model="selectedButtons"
All of your checkboxes are "modeling" one property.
You should use something in the lines of
<div v-for="(button, index) in buttons"....
.... v-model="selectedButtons[index]"
And by documentation Component v-model the v-model expands to :value="selectedButtons" @input="selectedButtons = event.target.value"
, so your :value="button.id"
is not used.
That way, each checkbox models exactly one property.
Hope this helps.
Best regards,
Mega Aleksandar