Laravel PATCH validation fails in controller

39 views Asked by At

My problem is similar to this post the different is I'm using modal to display the update fields. When I doing a PATCH request to my controller, my validation is failed on the required rules. I'm copying on how Laravel Breeze UpdateProfileInformation way to pass an form to new customized request and then proceed validate the rules there, if the validation works then it will dump the data.

But its always said "The xx field is required" although the request is already passed and filled with previous data Here is the codes :

Update.vue

<template>
    <div @click.self="closeModal()" class="backdrop">
        <div
            class="bg-base-100 justify-center items-center text-center w-[90%] h-fit p-5 m-auto mt-[3%] mb-[2%] overflow-auto rounded-md"
        >
            <slot class="w-fit h-fit">
                <div class="p-2 flex flex-col">
                    <div
                        class="font-semibold text-xl text-neutral-content leading-tight mb-5"
                    >
                        <h1>Update existing data</h1>
                    </div>
                    <form @submit.prevent="update">
                        <div
                            class="p-2 flex flex-row card bg-neutral rounded-md"
                        >
                            <div class="w-[50%] items-center p-2">
                                <div class="flex flex-col p-2">
                                    <div>
                                        <div v-if="tempUrl" class="p-5">
                                            <!-- M̶a̶k̶e̶s̶ C̶h̶e̶c̶k̶,̶ i̶f̶ o̶p̶e̶n̶ f̶i̶r̶s̶t̶ t̶i̶m̶e̶,̶ t̶a̶k̶e̶ i̶m̶g̶ u̶r̶l̶ f̶r̶o̶m̶ d̶b̶ a̶n̶d̶ d̶i̶s̶p̶l̶a̶y̶ i̶t̶ -->
                                            <!-- I̶f̶ t̶h̶e̶r̶e̶ i̶s̶ a̶ c̶h̶a̶n̶g̶e̶ i̶n̶ i̶m̶a̶g̶e̶,̶ c̶h̶a̶n̶g̶e̶ p̶r̶e̶v̶i̶e̶w̶ t̶o̶ c̶u̶r̶r̶e̶n̶t̶ s̶e̶l̶e̶c̶t̶e̶d̶ i̶m̶a̶g̶e̶ -->
                                            <h2 class="m-2">Preview Image</h2>
                                            <img
                                                class="m-auto rounded-md border-2 border-primary p-2"
                                                :src="tempUrl"
                                                alt=""
                                            />
                                        </div>
                                        <div v-else>
                                            <!-- Change to img later -->
                                            <h1>{{ form.image }}</h1>
                                        </div>
                                    </div>
                                    <div class="flex flex-col">
                                        <h1 class="m-2 text-start">Image</h1>
                                        <input
                                            id="image"
                                            @change="setImage"
                                            type="file"
                                            class="file-input file-input-sm rounded-md file-input-bordered file-input-primary w-full max-w-xs"
                                        />
                                        <InputError
                                            class="mt-2"
                                            :message="form.errors.image"
                                        />
                                    </div>
                                </div>
                                <div class="flex flex-col p-2">
                                    <div>
                                        <h1 class="m-2 text-start">Code</h1>
                                    </div>
                                    <div class="flex flex-row">
                                        <div v-if="radioCode">
                                            <TextInput
                                                id="codeText"
                                                v-model="form.code"
                                                type="text"
                                                placeholder="Type here"
                                                class="input input-bordered input-primary w-full max-w-xs"
                                                required
                                            />
                                            <InputError
                                                class="mt-2"
                                                :message="form.errors.code"
                                            />
                                        </div>
                                        <div v-else>
                                            <select
                                                id="codeSelect"
                                                v-model="form.code"
                                                class="select select-md select-primary w-full max-w-xs"
                                                required
                                            >
                                                <option disabled selected>
                                                    Existing Code
                                                </option>
                                                <option
                                                    v-for="furniture in Furnitures"
                                                >
                                                    {{ furniture.code }}
                                                </option>
                                            </select>
                                            <InputError
                                                class="mt-2"
                                                :message="form.errors.code"
                                            />
                                            <!-- Radio Group -->
                                        </div>
                                        <div class="ml-5 flex flex-col">
                                            <div class="flex flex-row">
                                                <input
                                                    type="radio"
                                                    name="radioCode"
                                                    class="mb-2 radio radio-sm radio-primary bg-inherit enabled:hover:border-info enabled:checked:bg-primary"
                                                    value="new"
                                                    @change="onChange($event)"
                                                    checked
                                                />
                                                <label for="radio" class="ml-2"
                                                    >New data</label
                                                >
                                            </div>
                                            <div class="flex flex-row">
                                                <input
                                                    type="radio"
                                                    name="radioCode"
                                                    class="radio radio-sm radio-primary bg-inherit enabled:hover:border-info enabled:checked:bg-primary"
                                                    value="exist"
                                                    @change="onChange($event)"
                                                />
                                                <label for="radio" class="ml-2"
                                                    >Existing data</label
                                                >
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Description</h1>
                                    <TextInput
                                        id="description"
                                        v-model="form.description"
                                        type="text"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.description"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Category</h1>
                                    <select
                                        id="category"
                                        v-model="form.category"
                                        @change="categoryChange"
                                        class="select select-md select-primary w-full max-w-xs"
                                    >
                                        <option v-for="category in categories">
                                            {{ category }}
                                        </option>
                                    </select>
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.category"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Wood Type</h1>
                                    <select
                                        id="woodtype"
                                        v-model="form.woodtype"
                                        class="select select-md select-primary w-full max-w-xs"
                                    >
                                        <option v-if="isRoot" value="Root">
                                            Root
                                        </option>
                                        <option
                                            v-if="!isRoot"
                                            v-for="notRoot in notRootType"
                                        >
                                            {{ notRoot }}
                                        </option>
                                    </select>
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.woodtype"
                                    />
                                </div>
                            </div>
                            <div class="w-[50%] items-center p-2">
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Width</h1>
                                    <NumberInput
                                        id="width"
                                        v-model="form.width"
                                        type="number"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.width"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Depth</h1>
                                    <NumberInput
                                        id="depth"
                                        v-model="form.depth"
                                        type="number"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.depth"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Height</h1>
                                    <NumberInput
                                        id="height"
                                        v-model="form.height"
                                        type="number"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.height"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Stock</h1>
                                    <NumberInput
                                        id="stock"
                                        v-model="form.stock"
                                        type="number"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.stock"
                                    />
                                </div>
                                <div class="flex flex-col p-2">
                                    <h1 class="m-2 text-start">Price</h1>
                                    <NumberInput
                                        id="price"
                                        v-model="form.price"
                                        type="number"
                                        placeholder="Type here"
                                        class="input input-bordered input-primary w-full max-w-xs"
                                    />
                                    <InputError
                                        class="mt-2"
                                        :message="form.errors.price"
                                    />
                                </div>
                            </div>
                        </div>
                        <div>
                            <button
                                class="btn m-4 px-10 btn-info"
                                :disabled="form.processing"
                            >
                                <div v-if="form.processing">
                                    <span
                                        class="loading loading-spinner loading-sm text-primary"
                                        >Update</span
                                    >
                                </div>
                                <div v-else>
                                    <span>Update</span>
                                </div>
                            </button>
                        </div>
                    </form>
                </div>
            </slot>
        </div>
    </div>
</template>

<script>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import PrimaryButton from "@/Components/PrimaryButton.vue";
import TextInput from "@/Components/TextInput.vue";
import NumberInput from "@/Components/NumberInput.vue";
import InputLabel from "@/Components/InputLabel.vue";
import { Link, useForm } from "@inertiajs/vue3";
import { ref } from "vue";
import InputError from "@/Components/InputError.vue";
export default {
    props: ["SelectedFurniture", "Furnitures"],
    components: {
        AuthenticatedLayout,
        PrimaryButton,
        TextInput,
        NumberInput,
        InputLabel,
        InputError,
    },
    setup(props) {
        const radioCode = ref(true);
        const categories = ["Indoor", "Outdoor", "Handicraft", "Root"];
        const notRootType = ["Teak wood", "Tiger wood", "Mahogany wood"];
        const isRoot = ref(false);
        const selectedCategory = ref("");
        let tempUrl = ref("");

        const form = useForm({
            uuid: props.SelectedFurniture.uuid,
            image: props.SelectedFurniture.image,
            code: props.SelectedFurniture.code,
            description: props.SelectedFurniture.description,
            category: props.SelectedFurniture.category,
            woodtype: props.SelectedFurniture.wood_type,
            width: parseInt(props.SelectedFurniture.width),
            depth: parseInt(props.SelectedFurniture.width),
            height: parseInt(props.SelectedFurniture.height),
            stock: parseInt(props.SelectedFurniture.stock),
            price: parseFloat(props.SelectedFurniture.price),
        });
        console.log(props.SelectedFurniture.wood_type);

        const update = () => {
            // console.log(form);
            form.patch(route("input.update"));
        };

        return {
            form,
            radioCode,
            categories,
            notRootType,
            isRoot,
            selectedCategory,
            tempUrl,
            update,
        };
    },
    methods: {
        closeModal() {
            this.$emit("close");
        },
        setImage(event) {
            const file = event.target.files;
            this.form.image = file[0];
            this.tempUrl = URL.createObjectURL(this.form.image);
            // console.log(this.tempUrl);
        },
        onChange(event) {
            this.radioCode = !this.radioCode;
            this.form.reset("code");
            // console.log(this.radioCode);
            // console.log(this.form);
        },
        categoryChange(event) {
            if (event.target.options.selectedIndex > -1) {
                this.selectedCategory = event.target.value;
                if (this.selectedCategory == "Root") {
                    this.isRoot = true;
                } else {
                    this.isRoot = false;
                }
                // console.log(this.isRoot);
                // console.log(this.selectedCategory);
            }
        },
    },
};
</script>

<style scoped>
.modal {
    width: 400px;
    padding: 20px;
    margin: 100px auto;
    background: white;
    border-radius: 10px;
    text-align: center;
}
.backdrop {
    top: 0;
    position: fixed;
    background: rgba(0, 0, 0, 0.5);
    width: 100%;
    height: 100%;
}
</style>

InputController

<?php

namespace App\Http\Controllers;

use Inertia\Inertia;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\InputUpdateRequest;

class InputController extends Controller
{
    //
    public function index(Request $request){
        $user = Auth::user();

        // dd($user);
        $furniture = DB::table('furniture')
        ->get();
        // dd($furniture);



    return Inertia::render('Input/Input', [
        'furnitures' => $furniture,
    ]);

    }

    public function create(Request $request){
        $validationInteger = "required|integer";
        $validationString = "required|string";
        $request -> validate([
            'image' => "required|file",
            'description' => $validationString,
            'category' => $validationString,
            'woodtype' => $validationString,
            'width' => $validationInteger,
            'height' => $validationInteger,
            'depth' => $validationInteger,
            'stock' => $validationInteger,
            'price' => $validationInteger,
        ]);

        // sleep(30);

        dd($request->all());
    }

    public function update(InputUpdateRequest $request){


            dd($request->all());



    }
}

InputUpdateRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class InputUpdateRequest extends FormRequest{

    public function rules(): array{
        $validationInteger = ["required","integer"];
        $validationString = ["required","string"];
        return [
            'uuid' => $validationString,
            'image' => ["required","file"],
            'description' => $validationString,
            'category' => $validationString,
            'woodtype' => $validationString,
            'width' => $validationInteger,
            'height' => $validationInteger,
            'depth' => $validationInteger,
            'stock' => $validationInteger,
            'price' => $validationInteger,
            ];
        }
}

Routers

Route::middleware('auth:admin')->group(function (){
    Route::get('/input',[InputController::class, 'index'])->name('input.index');
    Route::post('/input',[InputController::class, 'create'])->name('input.create');
    Route::patch('/input',[InputController::class, 'update'])->name('input.update');
    Route::delete('/input',[InputController::class, 'delete'])->name('input.delete');

});

I tried using sometimes rule, but it will causing endless loading,

When I dump the request normally, it's passing the data succesfully enter image description here

Edit :

I tried do the validation straight from the function itself still not working, but when I dump it, the requests is passed successfully

    public function update(Request $request){

        // dd($request->all());
        $validationInteger = "required|integer";
        $validationString = "required|string";
        $request -> validate([
            'image' => "required|file",
            'description' => $validationString,
            'category' => $validationString,
            'woodtype' => $validationString,
            'width' => $validationInteger,
            'height' => $validationInteger,
            'depth' => $validationInteger,
            'stock' => $validationInteger,
            'price' => $validationInteger,
            ]);
        dd($request->all());
    }
}
0

There are 0 answers