For storing issue in table in database we need to add following codes step by step in backend and frontend.
Step 01: Creating StoreIssueRequest.php using artisan command for validation of form fields
php artisan make:request StoreIssueRequest
Step 02: Adding validation rules like below in StoreIssueRequest.php making sure authorize function returns true
public function authorize(): bool { return true; }
public function rules(): array { return [ 'title' => 'required|string|max:255', 'description' => 'required|string', 'client_id' => 'required|exists:clients,id', 'image_name' => 'nullable|file|mimes:pdf,doc,docx,jpg,jpeg,png,gif,bmp,tiff', ]; }
Step 03: Now, Back in api/IssueController.php creating a new method store() like below for saving a issue with physically file saving capability. We will be using file input field later down this post from the frontend to upload and save this uploaded issue image from there.
// at the top
use App\Http\Requests\StoreIssueRequest; use App\Http\Resources\IssueResource;
public function store(StoreIssueRequest $request) { $issue = Issue::create($request->validated()); //dd($request->file('image_name')); if ($request->hasFile('image_name')) { $imagePath = $request->file('image_name')->store('issue_images', 'public'); } else { $imagePath = null; // No image uploaded } $issue->image_name = $imagePath; $issue->save(); return new IssueResource($issue); }
Step 04: Next in inside routes/api.php we need to add route apiResource method instead of route get to cover all the default controller methods ( index, store, edit, delete ) for api end points
Route::apiResource('issues', App\Http\Controllers\Api\IssueController::class );
Step 05: Next inside resources\js\composables\issues.js composable we need to add storeIssue() method to store form submitted input values like below
// at the top import { useRouter } from 'vue-router' export default function useIssues() { ..... const router = useRouter() const storeIssue = async (issue) => { axios.post('/api/issues', issue) .then(response => { router.push({ name: 'issues.list' }) }) } return { issues, getIssues, storeIssue } }
Step 06: Now we need to link with storeIssue() method above inside form element in resources\js\components\Issues\Create.vue component with vue submit method like below
<form @submit.prevent="storeIssue(issue)">
Step 07: Now this issue variable inside storeIssue() method needs to be reactive like below
const issue = reactive({ title: '', description: '', client_id: '', file: null })
Step 08: We also need to add necessary changes for incorporating composition method storeIssue(). Also we have added handleFileUpload() method which will be used later by file input placed inside form element.
import useIssues from "../../composables/issues"; const { storeIssue } = useIssues(); const handleFileUpload = (event) => { issue.file = event.target.files[0]; }
Step 09: Now we need to add v-model directive for all the input fields inside form element of template tag
<div class="mb-3"> <label for="email">Title:</label> <input type="text" class="form-control" id="text" placeholder="Enter title" name="title" v-model="issue.title"> </div> <div class="mb-3"> <label for="email">Description:</label> <textarea class="form-control" rows="5" id="description" name="description" v-model="issue.description"></textarea> </div> <div class="mb-3"> <label for="pwd">Client:</label> <select id="client_id" class="form-control" v-model="issue.client_id"> <option value="" selected>-- Choose client --</option> <option v-for="client in clients" :value="client.id"> {{ client.name }} </option> </select> </div> <div class="mb-3"> <label for="formFile" class="form-label">File Upload</label> <input class="form-control" type="file" id="formFile" v-on:change="handleFileUpload"> </div> <button type="submit" class="btn btn-primary bg-dark text-white cursor-not-allowed"> <span>Save</span> </button>
So, after all these steps implemented now we can fill up input fields with client dropdown and save these to db after submitting the form.