In the previous part, we have learned how to create and listen to events. We have implemented functionality for all three buttons which emit custom events named details
, update
and delete
and now we are going to implement functionalities for these events.
For the complete series navigation visit: Vue.js Series.
To download the source code for this part, visit Details and Deleting Owner Entity Source Code.
This post is divided into several sections:
Creating Owner Details Component
In the previous part, we have created the custom details
event and an event listener for that event. In the event handler, we’ve used the id
parameter from the owner
 object we have clicked on, and now we are going to use that id
to get the owner’s details. To accomplish that, we need to create a new component in which we are going to render the owner’s data.
Let’s do exactly that.
Creating a Component
Let’s Navigate to the src/components/owner
directory and create the OwnerDetails.vue
file:
<template> <div> <div class="well"> <div class="row"> <div class="col-md-3"> <strong>Owner name:</strong> </div> <div class="col-md-3"> {{ owner.name }} </div> </div> <div class="row"> <div class="col-md-3"> <strong>Date of birth:</strong> </div> <div class="col-md-3"> {{ owner.dateOfBirth }} </div> </div> <div v-if="owner.accounts && owner.accounts.length <= 2" class="row"> <div class="col-md-3"> <strong>Type of user:</strong> </div> <div class="col-md-3"> <span class="text-success">Beginner user.</span> </div> </div> <div v-else class="row"> <div class="col-md-3"> <strong>Type of user:</strong> </div> <div class="col-md-3"> <span class="text-info">Advanced user.</span> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>Account type</th> <th>Date created</th> </tr> </thead> <tbody> <tr v-for="account in owner.accounts" :key="account.id"> <td>{{ account.accountType }}</td> <td>{{ account.dateCreated }}</td> </tr> </tbody> </table> </div> </div> </div> </div> </template> <script> import OwnerService from '@/api-services/owner.service'; export default { name: 'OwnerDetails', data() { return { owner: {} }; }, created() { OwnerService.getAccounts(this.$router.currentRoute.params.id).then((response) => { this.owner = response.data; }); } }; </script>
The code snippet is pretty self-explanatory but however, let’s analyze it.
Component’s Code Explanation
We have the template with some interpolations to display owner’s name, birthday, etc. There is a conditional rendering as well, which will conditionally display Beginner user
or Advanced user
text based on the number of accounts related to the owner entity. In the script tag, we have the created
lifecycle hook in which we fetch an owner’s id
from a query string with the this.$router.currentRoute.params.id
expression and then fetch a data from the backend for that owner.
Implementing an API Service and Routing to the Component
Now, let’s create the getAccounts
method in our OwnerService
:
... delete(id) { return Axios.delete(`${RESOURCE_NAME}/${id}`); }, getAccounts(id) { return Axios.get(`${RESOURCE_NAME}/${id}/account`); } };
We still need to create the route for this component.
To do that, we are going to edit the src/router/index.js
file:
{ path: '/owner/list', name: 'OwnerList', component: OwnerList }, { path: '/owner/:id', name: 'OwnerDetails', component: OwnerDetails }, { path: '*', name: 'NotFound', component: NotFound }
We have just defined a new route which will accept
id
as a parameter through the query string. We can access the route parameters in our components through the this.$router.currentRoute.params
object.
Finally, we need to navigate to this component when we click on the Details
button in the owner list table.
Let’s edit the src/components/owner/OwnerList.vue
file:
detailsOwner(ownerId) { this.$router.push({ name: 'OwnerDetails', params: { id: ownerId } }); },
Great!
Now, we are going to open a terminal and type the npm run dev
command to view results:
Everything looks perfect.
Now let’s implement the Delete
functionality.
Deleting the Owner Entity
When a user clicks on the Delete
button, the confirmation dialog needs to show up. If we confirm the delete action, a request will be sent to the server. The server may respond with 204 (No Content) status code which means that we have successfully deleted the owner entity.
Otherwise, the server may respond with one of the error messages, depending on what went wrong. In both outcomes, we will display a modal which will inform us if our action was successful or not.
So, let’s summarize it.
We are going to create two modals. One is confirmation modal which has a static content and the second one is a modal which will inform us about the response of the delete request. So, in the second one, we are going to implement the data binding because we need to display different messages depending on the server response.
Creating a Component
Let’s navigate to the OwnerList.vue
component and implement that data binding action:
<template> <div> <b-row> <b-col md="2" offset-md="10"> <a href="#">Create owner</a> </b-col> </b-row> <br> <b-row> <b-col md="12"> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>Owner name</th> <th>Owner address</th> <th>Date of birth</th> <th>Details</th> <th>Update</th> <th>Delete</th> </tr> </thead> <tbody> <owner-list-row v-for="owner in owners" :key="owner.id" :owner="owner" @details="detailsOwner" @update="updateOwner" @delete="deleteOwner"/> </tbody> </table> </div> </b-col> </b-row> <b-modal ref="deleteConfirmModal" title="Confirm your action" @ok="onDeleteConfirm" @hide="onDeleteModalHide"> <p class="my-4">Are you sure you want to delete this owner?</p> </b-modal> <b-modal ref="alertModal" :title="alertModalTitle" :ok-only="true"> <p class="my-4">{{ alertModalContent }}</p> </b-modal> </div> </template> <script> import OwnerService from '@/api-services/owner.service'; import OwnerListRow from '@/components/owner/OwnerListRow'; export default { name: 'OwnerList', components: { OwnerListRow }, data() { return { owners: [], selectedOwnerId: null, alertModalTitle: '', alertModalContent: '' }; }, created() { this.fetchOwners(); }, methods: { detailsOwner(ownerId) { this.$router.push({ name: 'OwnerDetails', params: { id: ownerId } }); }, updateOwner(ownerId) { console.log('update', ownerId); }, deleteOwner(ownerId) { this.selectedOwnerId = ownerId; this.$refs.deleteConfirmModal.show(); }, fetchOwners() { OwnerService.getAll().then((response) => { this.owners = response.data; }); }, onDeleteConfirm() { OwnerService.delete(this.selectedOwnerId).then(() => { this.alertModalTitle = 'Successfully'; this.alertModalContent = 'Successfully deleted Account Owner'; this.$refs.alertModal.show(); this.fetchOwners(); }).catch((error) => { this.alertModalTitle = 'Error'; this.alertModalContent = error.response.data; this.$refs.alertModal.show(); }); }, onDeleteModalHide() { this.selectedOwnerId = null; } } }; </script>
First, let’s analyze the script part.
Component’s Code Explanation
We have moved a fetch owner logic from the created
lifecycle hook to the method named fetchOwners
. That’s because we need to fetch all the owners again after we successfully delete one owner. Now that we’ve moved the logic to the method, we can reuse our fetch owner code.
Next up, we create some data variables. In the selectedOwnerId
variable we are going to store the id
parameter from the owner entity we want to delete. In the remaining two variables we will store the title and the content for the second modal.
Let’s take a look at the this.$refs
statement. We use it for the first time and we are going to explain it right now.
In the template part, we have two modals. On both modals, we have the ref=”something”
attribute. Just as we can get an element in a vanilla JavaScript with the document.getElementById()
expression, we can get a reference to the element (or another vue component, b-modal in this case) in the Vue.js by using the ref
and this.$refs
statements. We can use these references to the modals to trigger the show()
method inside them. The rest of the template is also self-explanatory.
Inspecting the Results
Let’s again open a terminal and run the npm run dev
command to view results.
If we try to delete Anna Bosh
, the confirmation modal will show up:
When we click on the OK
button, the error appears because Anna Bosh
have the related accounts:
If we try to delete Nick Somion
, the confirmation dialogue shows up again:
And the successfully
message shows up:
Conclusion
By reading this post you’ve learned:
- How to handle server errors
- How to reference elements or components from the template
- And how to create a confirmation dialogue
In the next part of the series, we are going to implement creating and deleting the Account Owner and with that, we are finalizing or application development.
Access to XMLHttpRequest at ‘https://localhost:44374/api/owner/f522ca62-186d-4c38-af0e-7b9302d30295’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Method DELETE is not allowed by Access-Control-Allow-Methods in preflight response.
sservices.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
});
i dont think there is an issue with the cors on asp.net core can’t get where am i missing out
Getting the same issue for POST and PUT though i am able to get data
Postman is working fine with all requests
Had issues with
app.UseCors();
in startup file didn’t pass the policy name adding policy name workedapp.UseCors("CorsPolicy")
;thanks for the great tutorials