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.exportsobject in the routes/player.js file, define a neweditPlayerPagefunction withrequestandresponseparameters - In the body of the
editPlayerPagefunction, logrequest.params.idto the console - Under the log, use
request.renderto 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.getcalls, add anotherapp.getto hook up/edit/:idtoplayer.editPlayerPage- This means that whatever comes after the
edit/will be mapped to theidproperty ofparamsin the handler
- This means that whatever comes after the
- Navigate to the
/edit/5route and verify that5is 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
thto thetableheader row with the text "Action" - Within the
forloop row, add anothertdunder the numbertd - Within the new
td, add anawith the text "Edit" that points the user to/edit/with the player'sid - Set the
classattribute of theato "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
asyncfunction that takesplayerIdas a parameter - In the body of the function, create a new variable named
player - Use
db.getto get the value for the player given theplayerId - Use the
awaitkeyword to properly return the value - Under that, set the
"id"property of theplayerobject 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
editPlayerPagefunction - Declare a new variable
playerIdand set it torequest.params.id - Under that, declare a new variable named
playerObj - Use
db.getPlayerByIdto get the player data forplayerId - Use the
awaitkeyword to properly return the value - Make the
editPlayerPagefunction asynchronous with theasynckeyword - Use
console.logto 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
addPlayerPagefunction - At the top of the function body, create a new variable named
renderData - Set the
renderDatavariable to a JS object with two properties:playerandadd - Set
playerto an empty object, andaddtotrue - In the call to
response.render, pass inrenderDataas the second argument
editPlayerPage
- Find the
editPlayerPagefunction - Under the existing code, create a new variable named
renderData - Set the
renderDatavariable to a JS object with two properties:playerandadd - Set
playertoplayerObj, andaddtofalse - Call
response.render, passing inedit-playerandrenderData
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
inputfor "First Name" and add avalueattribute - Set the
valueattribute to an EJS segment that takes thefirst_nameproperty from theplayerobject - Using a ternary operator, update the EJS segment so that if
addistrue, it returns an empty string:<%= add ? '' : player.first_name %> - Make similar updates for the "Last Name" and "Number"
inputelements - For the "Position"
select, create a newoptionwith theselectedattribute containing an EJS segment withplayer.position - Wrap the new
optionin 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
formelement, update theactionattribute so that it can either go to/addOR/edit/{player.id}:action="/<%= add ? 'add' : `edit/${player.id} `%>" - Wrap the entire
formelement 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 anelseEJS scriptlet with apthat 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>