Building a simple application using Nuxt.js/Vue.js and Django — Part III

Eduardo da Silva
7 min readJul 6, 2020

--

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.

Photo by Goran Ivos on Unsplash

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 corresponding id.
  • PUT /api/pools/{id}/- Update the attributes and choices of the question (pool) with the corresponding id.
  • DELETE /api/pools/{id}/-Delete the question (pool) with the corresponding id.

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 page — Wireframe

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.

The frontend/pages/admin/question.vue file

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.

The frontend/components/questions/ListQuestions.vue — listQuestions components

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.

The frontend/components/questions/FormQuestion.vue file — The formQuestion component

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.

The frontend/components/questions/ListChoices.vue file — ListChoices 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.

The frontend/components/questions/FormChoice.vue file — FormChoice 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.

Photo by Daniel Mingook Kim on Unsplash

--

--

Eduardo da Silva

Professor at Catarinense Federal Institute (Brazil), PhD on Computer Science.