Node Guide

Menu
Menu

CRUDing with JSX

Building a CMS

Having now built queries for different ways to view the data (the R of CRUDing), we will next add the ability to create a new document, update it and delete it. This will form a seperate part of the web application called a CMS (Content Management System).

Later we'll secure with a login/passoword but for now we'll just create the functionality. The controller login will be very similar to the queries already built for the API.

Setting Up a CMS Home Page

To keep code manageable create a new route file of src/routes/cmsroutes.ts.

Add a GET call to the homepage:

src/routes/cmsroutes.ts

The route will call the same getAllData() method used in a previous file but we will send it a different title.

Add this new router file to the entry index.ts file:

SNIPPET: src/index.ts

By adding app.use("/cms", cmsroutes) all paths in the cmsroutes.ts can be relative ie / will reference localhost:3000/cms/ and /edit will reference localhost:3000/edit.

There is already a view set up at src/views/cms.ejs that will be rendered by a request of localhost:3000/cms/. This page lists all the films, and we will later add links so that data can be edited or deleted.

Notice that the view does contain an "Add New" link from where we will be able to add a new document to the collection.

Adding a GET and POST Route for Inserting a Document

Notice there is a view set up at src/view/insert.ejs. This holds a HTML form with fields that match those in the model.

To add a new document, a user will initially navigate to this view via a GET call, as such this requires a simple route to be added of:

SNIPPET: src/routes/cmsroutes.ts

The GET call will render the src/view/insert.ejs view. The HTML form inside the view has a method of POST set. As such when the form is submitted a POST request will be made to the application which will send the user inputted data through with the request.

This is done through the request.body. In an Express application, when a client makes an HTTP POST request and includes data in the body of the request, the server can access that data through the request.body property. The request object represents the incoming HTTP request, and the body property contains the parsed body of the request.

Add the POST request with:

SNIPPET: src/routes/cmsroutes.ts

If the call to createData() method is successful, the user is redirected via the response objects res.redirect method. In this case the user is redirect back to localhost:3000/cms/.

Adding a Create Method in the CMS Controller

With the routes set up we now need to create the createData() method.

Again, to keep things tidy we'll create a new controller specifically for the CMS. Create a file src/controller/cmscontroller and add the following:

src/controllers/cmscontroller.ts

First we import the Film calls and IFIlm interface from the src/models/Film module.

The createData asynchronous function takes a parameter named data, which is of type Partial<IFilm>. The Partial<T> type in TypeScript allows properties of T to be optional, meaning not all properties of IFilm need to be provided. The function then calls the create() method to create a new document which is returned if done successfully.

Note: Ensure you import the cmscontroller into the route file.

You should now be able to add a new document/film to the collection.

Adding a GET and POST Route for Editing a Document

For editing we will require to have two queries, one to get the current values and one to execute anhy update.

As such we will again need two routes, a GET call to show the edit page and a POST call to update the data. Notice with the GET call we will need to query the database to get the current document. Again, we already have a function for this in the src/controllers/controller file called getDataById so we'll reuse this. Add the following to src/routes/cmsroutes.ts

SNIPPET: src/routes/cmsroutes.ts

To arrive at this page edit the src/views/cms.ejs to make the text 'edit' a hyperlink that passes the id as a URL Parameter

SNIPPET: src/views/cms.ejs

When the link is following the URL parameter is used in the getDataById to retrieve the data for film. In the view at src/views/edit.ejs see how the values are used to populate the HTML form with the correct values.

Note: In the view the id for the document is set as a hidden field so that we don't need to sent it in the URL when actually editing the page.

Next we need to add the POST request. You might expect a PUT request here inline with RESTful techniques, however in HTML forms the action method only supports GET and POST. We could use some Javascript to get around this but for our purposes it will be easier to just use a POST request for the edit form.

Add the following router:

SNIPPET: src/routes/cmsroutes.ts

When the POST call is made the request object body property is again used to send the data. We send the id and the entire body as two values to make the retrieval of the id easy for the controller.

If the call to updateData is successful the user if redirect with res.redirect("/cms/") as done with the insert example.

Adding a Update Method in the CMS Controller

Next add the controller method for the update.

SNIPPET: src/controllers/cmscontroller.ts

The updateData function expects an id and data, a partial from the HTML form. From these a findByIdAndUpdate query is run.

Note: Ensure you export the new updateData method from the controller.

The CMS should now allow the editing of documents.

Adding the GET and POST Delete Route

To add the delete funcionality a similar set up is required. First we need a GET to ensure the correct record is removed. Then a POST route to call a delete method (again because of the limitions of the HTML form method).

Set up the GET route as:

src/routes/cmsroutes.ts

To link to the delete page edit the src/views/cms.ejs to make the text 'delete' a hyperlink that passes the id as a URL Parameter

SNIPPET: src/views/cms.ejs

The GET call will use the src/views/delete.ejs to generate a page where the user can check to see if this the correct document to delete. They can choose to keep the document by simply navigating away, alternatively they can make a POST call to delete the record by submitting the form with a hidden field value for the id.

Set up the POST route as:

src/routes/cmsroutes.ts

Again, if successful the user is redirected to the CMS homepage.

Building the Delete Controller

The delete controller will appear as:

SNIPPET: src/controllers/cmscontroller.ts

The deleteData method receives the id of the document to remove from the collection doing so via convenient Mongoose findByIdAndDelete

Note: Ensure you export the new deleteData method from the controller.

Users should now be able to add, update and delete documents.

What we need to do next is limit who can do this.

Next: Setting up and Registering Users