Building a simple application using Nuxt.js/Vue.js and Django — Part III
In the first and the second part of this tutorial, we have implemented the authentication and backed CRUD module of our solution. Here, we are going the develop the basic frontend CRUD implementation, consuming the backend endpoints provided in the previous part.
The target
Now, we are going to implement the initial frontend interface of the pool system. We have already defined the endpoints to perform the basic operations to handle the system, including the creation, reading, updating, and deletion of pool tasks. By accessing such endpoints, we are now able to create the initial administration pages.
To recap, we have made available the following endpoints on the backend side:
- POST
/api/pools/
- Create a new question with the respective choice options. - GET
/api/pools
- Get the list of questions (pools) and their respective choice options. - GET
/api/pools/closed/
- Get the list of closed/expired questions (pools) and their respective choice options. - GET
/api/pools/active/
- Get the listof active questions (pools) and their respective choice options. - GET
/api/pools/{id}/
- Get the attributes and choices of the question (pool) with the correspondingid
. - PUT
/api/pools/{id}/
- Update the attributes and choices of the question (pool) with the correspondingid
. - DELETE
/api/pools/{id}/-
Delete the question (pool) with the correspondingid
.
Questions management — The layout
Initially, we created the main page to handle the pool questions. Note, on the below figure, that the page contains two blocks: a form to add or edit a question (superior part), and the questions listing (bottom part).
Questions management — The main structure
With the page sketch defined, we create the file to the question management on frontend/pages/admin/question.vue
. The below code presents such file content.
Lines 1–12 define the page template. Note that we defined an h1
tag to present the page title. Then, two components are rendered: form-question and list-questions, respectively. Such components were imported on lines 16 and 17. The former receives a question
object as a custom input (via v-model directive) and emits two custom events: save
and reset
. The latter one receives the questions
Array as a custom input and can emit two custom events: remove
and loadQuestion
.
Lines 14–81 contains the script code. Initially, we imported the previously cited components and registered them (line 18). The asynchronous method fetch()
(lines 19–21) is responsible for performing a get request on ‘api/pools
’ backend endpoint, which replies with the list of questions (pools) and their respective choice options, in a JSON object. The content of such a response is stored on questions
Array.
The method data()
(lines 22–30) initializes the question
object and questions
Array to be after referenced. Then, we create the save()
, loadQuestion()
, remove()
, and reset()
methods. For simplicity, I will not detail all such method, but only cite the main feature on each one.
The method save()
is responsible for performing a POST or a PUT request on ‘api/pools
’ URL. Note that if question.id
is already defined (line 33), then such an operation is supposed to be an edit (PUT method). Otherwise, we consider that a new question is being created (POST method). Then, we perform the request to the backend (line 37). This method is invoked when the save button is pressed. Such a button is defined on the formQuestion
component.
The method reset()
(lines 72–76) is invoked on the cancel button (from formQuestion
component) is pressed. Note that it occurs when the user is filling the form and wants to clean it. Then, we just redefine the question
object with the default values.
The method loadQuestion()
(lines 48–57) receives a question object via parameter and changes the value of question object with the corresponding attributes of received object. Such method is invoked from listQuestions
components, when the edit button is pressed. Then, a custom event is sent with the corresponding question object as parameter.
Finally, the method remove()
(lines 58–71) is responsible for performing a DELETE request to the backend, with the appropriate question ID to be removed. Line 61 is the core of such a method, in which the delete method of axios module is invoked.
The listQuestions component
Now, we implement the listQuestions
component, that is responsible for listing the questions on a table and emit to the question.vue
page the loadQuestion
and remove
events, as described on previous section.
The below code corresponds to the content of the frontend/components/questions/ListQuestions.vue
file.
Lines 1–37 render the table with questions received via the v-model
directive. We presented the data by using the b-table component from Buefy. More details can be found on the documentation. Note (line 2), that the data handled to be rendered on the table is store on the value
attribute. Such an attribute is defined as a prop
component on the script block (lines 41–46). The value
prop is corresponding to the custom input sent to the component via the v-model
directive.
In the sequence, questions are rendered on the table, field by field. Also, for each row rendered we added two buttons corresponding to the edit and remove operations, respectively (lines 20–33). Then, on clicking in such buttons, custom events are sent to the question.vue
page (as detailed in the previous section). The loadQuestion method (lines 47–49) emits the loadQuestion event sending the selected question as a parameter. The corresponding question is informed when the edit
button is clicked (lines 21–25 — props.row data).
A similar feature is found when the remove
button is clicked (lines 27–32). In such a case, first is presented a confirmation message to the user and, if he confirms the question deletion, the custom event remove is sent to the question.vue
page (line 59).
The formQuestion component
Then, we implement the formQuestion
component, that is responsible for handling the creation and update of questions. The below code corresponds to the content of the frontend/components/questions/FormQuestion.vue
file.
Note that in such a file we created a form, in which the fields are associated with the attributes of value
prop. As in the listQuestions
components, value
data is a prop. In this case, it is linked with the question
object from the question.vue
page.
When clicking on save
or reset
buttons (lines 40–45) the corresponding custom events are emitted (lines 68–73). In the question.vue
page, as already detailed, such custom events perform the cleaning of the form or send the POST / PUT method to the backend.
To recap, the backend endpoints send and receive questions data to and from the requester including choices info. Then, when creating or editing questions, it is needed to include such information in the form. Then, we create a structure similar to question one, to handle the choices.
To this, we create two components: listChoices and formChoice to list and add or edit the choices of a question, respectively. Such components are imported and registered in the script section (lines 52–55) and rendered on the template section (lines 31–37). Note that, as in the question components, we are sending custom inputs to the components and waiting for custom events.
Then, to handle the custom events sent by the choices-related components, we created the following methods: saveChoice()
, removeChoice()
, and loadChoice()
. Note that, in these methods, we are not performing the consumption of backend API yet, but only updating the choices
attribute of the corresponding question
object.
The choices-related components
The below code presents the listChoices component, on frontend/components/questions/ListChoices.vue file. Note that it is very similar to the ListQuestions
component.
Also, the formChoice component is simple and presented on the below code. As the previous components, this component is also stored on the frontend/components/questions/
directory. The fields of the form are associated with the value
data received via props
(through the v-model
directive) and, when click on save button, the saveChoice
custom event is emitted, and handled on formQuestion
component.
Updating the menu
Now we have properly implemented the new pool/question management page with their components, including the link to the Question admin page. Then, we edit the frontend/layout/default.vue
file, as follows:
Note that, compared with our previous version (from the part I of the tutorial) we have included just the lines 67–71 to the file, pointing the admin-question link to be rendered on the side menu.
Now, we can to test the new feature of the page. If your Nuxt is not running yet, open the console and run:
$ npm run dev
Then, open your favorite browser and access localhost:3000
. After the authentication process (presented in the first tutorial), the Question item will be presented on the side menu. The presented page must be similar to the presented on the below figure.
Final comments
In this part of tutorial, we presented the initial frontend solution consuming the REST API from the Django REST Framework, in order to handle questions and choices of a pool system.