CRUD App - Update (GET)
Add a form to the web app that will allow the user to edit the information for an existing player in the database. First, create an "Edit Player" route that will be accessible via a GET request.
Routing the GET Handler
The GET request for the "Edit Player" page requires a player id
to render. The id
can be passed as a route parameter in Express. The user should be able to direct their browser to http://<base-url>/edit/5
and the handler will know that the user would like to edit the player with an id
of 5
.
- In the
module.exports
object in the routes/player.js file, define a neweditPlayerPage
function withrequest
andresponse
parameters - In the body of the
editPlayerPage
function, logrequest.params.id
to the console - Under the log, use
request.render
to render the edit-player.ejs page:editPlayerPage: function (request, response) { console.log(request.params.id); response.render('edit-player'); }
- In the app.js file, under the
app.get
calls, add anotherapp.get
to hook up/edit/:id
toplayer.editPlayerPage
- This means that whatever comes after the
edit/
will be mapped to theid
property ofparams
in the handler
- This means that whatever comes after the
- Navigate to the
/edit/5
route and verify that5
is properly logged in the console as theid
!
Adding the Edit Buttons
Now that the "Edit Player" route exists, the user needs a way to navigate to it! Add "Edit" buttons for each player in the home page table.
- In the views/index.ejs file, add another
th
to thetable
header row with the text "Action" - Within the
for
loop row, add anothertd
under the numbertd
- Within the new
td
, add ana
with the text "Edit" that points the user to/edit/
with the player'sid
- Set the
class
attribute of thea
to "btn btn-sm btn-success" to make it appear like a green button:<td> <a href="/edit/<%= players[i].id %>" class="btn btn-sm btn-success">Edit</a> </td>
- Load up the homepage, and verify that the "Edit" button links to the "Edit" page for the proper player!
At this point, the player ID should simply be logged in the console. The program will end up using that ID to get the data for a player.
Updating the GET Handler Function
The GET handler function should query the database to find the information about the player with the given id
. It should then pass that data along to the EJS for rendering.
Getting the Data from the DB
Start by adding a way to get the player data from the database. Open the db.js file to begin.
- In the
module.exports
, add a new property namedgetPlayerById
- Make it an
async
function that takesplayerId
as a parameter - In the body of the function, create a new variable named
player
- Use
db.get
to get the value for the player given theplayerId
- Use the
await
keyword to properly return the value - Under that, set the
"id"
property of theplayer
object to theplayerId
- Finally, return
player
Code
getPlayerById: async function(playerId) {
let player = await db.get(playerId);
player["id"] = playerId;
return player;
}
Getting the Data
Open the routes/player.js file to begin.
- Remove the code currently in the body of the
editPlayerPage
function - Declare a new variable
playerId
and set it torequest.params.id
- Under that, declare a new variable named
playerObj
- Use
db.getPlayerById
to get the player data forplayerId
- Use the
await
keyword to properly return the value - Make the
editPlayerPage
function asynchronous with theasync
keyword - Use
console.log
to log the data to the console
Load up the homepage, click one of the "Edit" buttons, and verify that the data for that player appears in the console!
Updating the EJS
Currently, the edit-player.ejs file can only handle adding new players. Update the EJS so that it will dynamically handle adding or editing players. If it is editing an existing player, the player data should be auto-filled in the form.
Passing in the Render Data
Now that there are two different uses for the edit-player.ejs template, it will be necessary to pass in some data to distinguish them. Open the routes/player.js file to begin.
addplayerPage
- Find the
addPlayerPage
function - At the top of the function body, create a new variable named
renderData
- Set the
renderData
variable to a JS object with two properties:player
andadd
- Set
player
to an empty object, andadd
totrue
- In the call to
response.render
, pass inrenderData
as the second argument
editPlayerPage
- Find the
editPlayerPage
function - Under the existing code, create a new variable named
renderData
- Set the
renderData
variable to a JS object with two properties:player
andadd
- Set
player
toplayerObj
, andadd
tofalse
- Call
response.render
, passing inedit-player
andrenderData
Now, the template should have all the data it needs!
Updating the EJS File
This is the tricky part. It's time to update the EJS to handle all of the data, and make it work for both adding and editing players.
- In the edit-player.ejs file, find the
input
for "First Name" and add avalue
attribute - Set the
value
attribute to an EJS segment that takes thefirst_name
property from theplayer
object - Using a ternary operator, update the EJS segment so that if
add
istrue
, it returns an empty string:<%= add ? '' : player.first_name %>
- Make similar updates for the "Last Name" and "Number"
input
elements - For the "Position"
select
, create a newoption
with theselected
attribute containing an EJS segment withplayer.position
- Wrap the new
option
in an EJS scriptlet with anif (!add)
so that it only appears while editing an existing player - In the "Submit" button
input
, replace "Add" with an EJS segment that could be either "Add" or "Update":<%= add ? 'Add' : 'Update' %>
- In the main
form
element, update theaction
attribute so that it can either go to/add
OR/edit/{player.id}
:action="/<%= add ? 'add' : `edit/${player.id} `%>"
- Wrap the entire
form
element in an EJS scriptlet with anif (add || player)
- This means if the user attempts to edit a player that does not exist, the form will not render
- Under the
form
, add anelse
EJS scriptlet with ap
that says "Player Not Found."- Give it a class of
"text-center"
- Give it a class of
- Load up the "Edit Player" page for a given
id
, and verify that the proper player information appears- Note that the form will not be submittable yet!
- Load up the "Add Player" page, and verify that everything still works the same way
edit-player.ejs
<%- include('partials/header') %>
<div class="container">
<% if (add || player) { %>
<form method="post" action="/<%=add ? 'add' : `edit/${player.id}`%>">
<div class="form-row">
<div class="form-group col-md-6">
<label for="first-name">First Name</label>
<input type="text" class="form-control" name="first_name" value="<%=add ? '' : player.first_name%>" required>
</div>
<div class="form-group col-md-6">
<label for="last-name">Last Name</label>
<input type="text" class="form-control" name="last_name" value="<%=add ? '' : player.last_name%>" required>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="number">Number</label>
<input type="number" class="form-control" name="number" value="<%=add ? '' : player.number%>" required>
</div>
<div class="form-group col-md-6">
<label for="position">Position</label>
<select name="position" class="form-control" required>
<% if (!add) { %>
<option selected><%= player.position %></option>
<% } %>
<option>Goalkeeper</option>
<option>Defender</option>
<option>Midfielder</option>
<option>Forward</option>
</select>
</div>
</div>
<button type="submit" class="btn btn-success float-right"><%= add ? 'Add' : 'Update' %> Player</button>
</form>
<% } else { %>
<p class="text-center">Player Not Found.</p>
<% } %>
</div>
</div>
</body>
</html>