phpvuejs3inertiajslaravel-11

Storing checked box data to the database in laravel inertia vue js


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


Solution

  • 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