Issue edit form and routing with parameter

Step 01: Creating Edit.vue component under resources/js/components/Issues folder with static text

<template>    
    <h1>Edit Client Issue </h1>
    <div class="card mt-3">
        <div class="card-body">
        </div>
    </div>      
</template>

Step 02: Adding edit link in a separate column inside Index.vue component under resources/js/components/Issues folder

// adding tbl header 
<th>Actions</th>

// adding edit link inside tbl 
<td>
    <router-link :to="{ name: 'issues.edit', params: { id: issue.id } }">Edit</router-link>
</td>

Step 03: Now clicking on edit link wont work. In order work clicking we need to add following changes in resources/js/routes/index.js

// importing newly created Edit.vue component 
import IssuesEdit from '../components/Issues/Edit.vue' 

// adding edit route in routes variable 
{ path: '/edit-issue/:id', name: 'issues.edit', component: IssuesEdit, meta: { title:  'Issue Edit' } },

Step 04: Now adding edit form copying template and script tag of Create.vue component

<template>    
    <h1>Edit Client Issue </h1>
    <div class="card mt-3">
        <div class="card-body">
            <form @submit.prevent="updateIssue(issue)">
                    <div class="mb-3">
                    <label for="email">Title:</label>
                    <input v-model="issue.title" type="text" class="form-control" id="text" placeholder="Enter title" name="title">                               
                    <div v-for="message in validationErrors?.title">
                        <span class="text-danger">{{ message }}</span>
                    </div>
                    </div>
                    <div class="mb-3">
                    <label for="email">Description:</label>
                    <textarea v-model="issue.description"  class="form-control" rows="5" id="description" name="description"></textarea>                              
                    <div v-for="message in validationErrors?.description">
                        <span class="text-danger">{{ message }}</span>
                    </div>
                    </div>                                
                    <div class="mb-3">
                        <label for="pwd">Client:</label>
                        <select v-model="issue.client_id" id="client_id" class="form-control" name="client_id">
                            <option value="" selected>-- Choose client --</option>
                            <option v-for="client in clients" :value="client.id"> 
                                {{ client.name }} 
                            </option> 
                        </select>      
                        <div v-for="message in validationErrors?.client_id">
                            <span class="text-danger">{{ message }}</span>
                        </div>
                    </div>
                    <!-- <button type="submit" class="btn btn-primary cursor-not-allowed">
                        <span>Save</span>                                    
                    </button> -->
                    <button :disabled="isLoading" type="submit" class="btn btn-primary cursor-not-allowed">
                        <span v-show="isLoading" class="spinner-border p-2">&nbsp;</span>
                        <span v-if="isLoading">&nbsp;&nbsp;Processing...</span>
                        <span v-else>Save</span>                             
                    </button>                    
                </form>
        </div>
    </div>      
</template>

<script setup>
import { reactive, onMounted } from 'vue';
import useClients from "../../composables/clients";
import useIssues from '../../composables/issues';


const { clients, getClients } = useClients()
const { storeIssue, validationErrors, isLoading } = useIssues() 

onMounted(() => {
    getClients()
})

</script>

Step 05: Now we need to add a new method updateIssue() in issues.js composable like below to get a new issue with parameter

export default function useIssues() {
    const issue = ref({})
    .....
    const getIssue = async (id) => { 
        axios.get('/api/issues/' + id)
            .then(response => {
                issue.value = response.data.data;
            })
    } 

    return { issues, getIssues, storeIssue, validationErrors, isLoading, issue, getIssue }    
}

Step 06: Now we need to create show() method in backend api/IssueController.php to recieve single issue data from this end point

 public function show(Issue $issue) {
     return new IssueResource($issue);
 } 

Step 07: Then we need to fetch this issue data inside Edit.vue component with following code using useRoute() method of vue-router composable

 // importing vue-router 
 import { useRoute } from "vue-router";
 
 // loading issue and getIssue from issues composable 
 const { storeIssue, validationErrors, isLoading, issue, getIssue } = useIssues()
 
 // instance of useRoute() 
 const route = useRoute()
 
 // calling getIssue with route parameter 
 onMounted(() => {
    getIssue(route.params.id) 
    ....
})

Step 08: Until now if we refresh the page we will see form is populating the issue data except for client_id which is not being returned from api endpoint. To do this following code is needed

// in IssueResource adding client_id 
return [
    ...    
    'client_id' => $this->client_id,
    ...
];

Now if we refresh the form we will see client_id is also getting populated

Related Posts


Seeding users and role_user data

Seeding clients and issues data

Adding client column in table

Storing issue in db table

Update issue

Showing user data and logout

Permission securing backend

Permission securing frontend