WEBVTT 0 00:00.690 --> 00:08.910 So in the last lesson we looked at how we are able to add new items into our ToDo list by switching 1 00:08.940 --> 00:11.620 our database from an array over to MongoDB. 2 00:11.620 --> 00:17.400 In this lesson I want to look at the other functionality that we promise people which is that when 3 00:17.420 --> 00:22.950 we click on one of these text boxes it should be able to delete an item. At the moment 4 00:22.980 --> 00:24.140 it doesn't really do that. 5 00:24.150 --> 00:25.730 It just crosses it out. 6 00:26.010 --> 00:33.540 But say if we had a really long todo list and we had a whole bunch of stuff then it kind of clutters 7 00:33.540 --> 00:35.640 the page and we just click on that 8 00:35.640 --> 00:35.990 right? 9 00:36.000 --> 00:39.260 It doesn't really need to be there anymore after I've checked it off. 10 00:39.270 --> 00:41.280 I want to clear out my list. 11 00:41.490 --> 00:48.030 So I want to be able to delete the item when I click the check box next to it. And to do that we have 12 00:48.030 --> 00:55.800 to remove that particular document from items collection. Inside our list. 13 00:55.840 --> 00:56.290 ejs 14 00:56.320 --> 00:57.720 you can see that 15 00:57.740 --> 01:05.570 currently we have this input called checkbox and next to it we have the item name in a paragraph. 16 01:05.740 --> 01:13.720 If we wanted to send some data when that checkbox gets clicked then we need again a form and a post 17 01:13.720 --> 01:14.490 route. 18 01:14.500 --> 01:25.010 So let's go ahead and create a new form and we're going to wrap that form around our items div. Once 19 01:25.020 --> 01:30.460 we've grouped our input and a paragraph into this new form 20 01:30.480 --> 01:37.560 the first thing that you notice when you hit save and you go back over to our todo list is when you 21 01:37.560 --> 01:41.160 refresh the styling looks a bit different 22 01:41.160 --> 01:41.390 right? 23 01:41.400 --> 01:42.940 It looks a bit off. 24 01:43.140 --> 01:46.290 And the reason for this is because in our stylesheet, 25 01:46.380 --> 01:53.490 so if you go into public, css, styles.css, you can see that we have the CSS rule which is targeting 26 01:53.940 --> 02:02.520 our HTML form elements and this will apply the text-align center and margin-left to all of our form elements 27 02:02.850 --> 02:04.230 which is not what we want. 28 02:05.010 --> 02:08.860 We only want it for this form and not this one. 29 02:09.000 --> 02:11.090 So what's the difference here? 30 02:11.430 --> 02:14.990 Well this one has a class of item. 31 02:15.240 --> 02:18.500 So it's got a class and it's also a form element. 32 02:18.750 --> 02:25.320 So if we wanted our CSS to be more specific then we could say for this rule it should only apply 33 02:25.320 --> 02:32.320 to all of the HTML forms which also have the class item. 34 02:32.340 --> 02:38.970 Now if we hit save and we go back to our To-Do list and hit refresh then you can see that our previous 35 02:38.970 --> 02:41.380 styles are restored. 36 02:41.430 --> 02:49.410 So now that we fixed the CSS and styling, the next thing to address is where is this form going to post 37 02:49.410 --> 02:56.640 to? Well in order to specify that we need an action and a method right? 38 02:56.890 --> 03:03.340 So if we just go ahead and copy those into this form element then the part that we're going to keep 39 03:03.340 --> 03:10.450 the same is this form is also going to make a post request but the route is now going to be separate 40 03:10.570 --> 03:12.860 from what we had down here. 41 03:13.270 --> 03:16.240 This route was responsible for adding new items, 42 03:16.240 --> 03:20.600 so this route has to be responsible for deleting checked items. 43 03:20.620 --> 03:26.540 Let's add a route called /delete and hit save. 44 03:26.620 --> 03:35.860 Now inside our app.js just below our other posts route we can add this new route. So we can say 45 03:35.950 --> 03:45.460 app.post and the route was called /delete and this also is going to have a callback, req and 46 03:45.480 --> 03:52.590 res and now I'm going to console log simply request.body 47 03:52.590 --> 04:00.090 so what is being sent over basically from our form inside list.ejs because we know that over here in 48 04:00.090 --> 04:09.000 our app.post we're getting the new item being sent over because in that form we have an input with 49 04:09.000 --> 04:16.320 type text and has the name of new item and we're going to send over whatever it is that the user typed 50 04:16.320 --> 04:20.980 in here over to this route via the req.body. 51 04:21.300 --> 04:28.760 If we run our app now let's see what our console logs for the req.body of our /delete 52 04:28.780 --> 04:31.250 route. 53 04:31.460 --> 04:37.250 I'm going to refresh my to-do list and I'm just going to check one of these boxes. 54 04:37.490 --> 04:44.120 And if we have a look inside our console then you can see that absolutely nothing happens here. 55 04:44.440 --> 04:52.310 And the reason is because inside our list.ejs, if you remember we actually have this button 56 04:52.350 --> 04:56.550 here and it's type is submit. 57 04:56.780 --> 05:03.560 And whenever we have a submit button anywhere inside a form then its job is that when it gets pressed 58 05:03.740 --> 05:12.170 it will submit all of the data inside the form and make the post request to the required route. 59 05:12.170 --> 05:20.990 Now in this form however we don't have any way of submitting and it'll look kind of ugly if we added a submit 60 05:20.990 --> 05:23.510 button next to the checkbox right? 61 05:23.510 --> 05:30.260 I mean, ideally what we want is whenever we tick a checkbox we just want it to be able to delete that 62 05:30.290 --> 05:31.430 item. 63 05:31.430 --> 05:35.840 The action has to happen when we check the checkbox. 64 05:36.240 --> 05:41.400 So how can we get the form to submit when the checkbox is checked? 65 05:42.520 --> 05:48.420 Well if we didn't have any better ideas then we can always ask a developer's best friend 66 05:48.460 --> 05:48.890 right? 67 05:49.000 --> 05:49.860 It's Google. 68 05:49.960 --> 05:57.480 So if we put in the query "submit form when checkbox is checked" for example. 69 05:57.850 --> 05:59.920 That seems pretty much like what we want. 70 06:00.160 --> 06:06.880 And if we click on the first Stack Overflow answer, then the person is asking how do you submit a form 71 06:06.880 --> 06:08.890 when a checkbox is checked. 72 06:08.890 --> 06:10.580 Sounds like what we want too. 73 06:10.730 --> 06:18.650 So if you scroll down, the first answer tells us that in plain Javascript simply add this attribute on 74 06:18.650 --> 06:23.560 change to the input that is going to change and then inside it 75 06:23.560 --> 06:28.850 just add a little snippet of Javascript code to submit the current form. 76 06:28.870 --> 06:33.490 Let's go ahead and copy this over to our input. 77 06:33.490 --> 06:37.640 The input that we want to trigger the submit is of course our checkbox. 78 06:37.870 --> 06:44.980 In addition to having a type it's now also going to have a onChange attribute. And so that means when 79 06:44.980 --> 06:46.530 the checkbox is changed, 80 06:46.570 --> 06:53.140 so from checked to unchecked, unchecked to checked, then we're going to run this line of Javascript code 81 06:53.470 --> 06:57.350 which will take the current form that the input is inside, 82 06:57.490 --> 07:05.560 so this one, and it's going to submit it to make that post request to our delete route. 83 07:05.950 --> 07:13.330 In addition to just getting the form to submit we also need a way of accessing this input. To do that 84 07:13.360 --> 07:18.040 we have to give it a name. For our text input to add new items 85 07:18.040 --> 07:24.360 we gave it a name of newItem which is what allowed us to tap into it inside the req.body. 86 07:24.910 --> 07:30.130 So for this check box we're also going to give it a name and I'm going to give it something really simple. 87 07:30.130 --> 07:32.480 I'm just going to call it checkbox. 88 07:33.040 --> 07:42.250 So now if we save our code and go back to our console and refresh our page then I'm going to click on 89 07:42.250 --> 07:44.670 one of these boxes to check it. 90 07:44.740 --> 07:53.760 And now if I have a look inside my console you can see that I've got the "on" value printed for my check 91 07:53.760 --> 08:01.780 box. And this comes from the log statement that's inside my app.js inside this route. 92 08:01.840 --> 08:05.110 This is what is being logged right now. 93 08:05.110 --> 08:08.480 And of course I can now tap into this thing called checkbox. 94 08:08.680 --> 08:16.870 So if I hit save now and I refresh my page and go back to my root route, refresh my page and check one 95 08:16.870 --> 08:18.510 of the items, you can see 96 08:18.510 --> 08:27.580 I now get the value of that req.body which is "on". On is not very useful for us 97 08:27.590 --> 08:28.320 right? 98 08:28.340 --> 08:34.290 What we want is the item name that they actually checked off. 99 08:34.500 --> 08:43.800 So we know that our forEach loop is going to render as many checkboxes as we have items in our items 100 08:43.800 --> 08:45.010 collection. 101 08:45.060 --> 08:56.240 That means that we can also assign a value to our checkbox based on the item's ID. Inside here I'm going 102 08:56.240 --> 09:04.780 to add another attribute called value and this value is going to be equal to some EJS values. 103 09:04.850 --> 09:11.060 So I'm going to add that classic angle bracket percentage equal sign and then I'm going to close it 104 09:11.060 --> 09:14.610 off with percent angle bracket. And inside here 105 09:14.630 --> 09:22.730 I'm going to tap into that item object that we get access to and I'm going to tap into its ID. 106 09:22.970 --> 09:29.740 Remember, when we pass new list items over we're passing over an array of Mongo documents. 107 09:29.900 --> 09:37.310 Each of these documents or each of these items that we're looping through has a name as well as an ID. 108 09:37.550 --> 09:45.860 So if I bind that ID to the value of each of the checkboxes then when it gets checked I can submit this 109 09:45.860 --> 09:50.210 form and find out which item was actually checked off. 110 09:50.690 --> 09:58.460 So now let's hit save and let's again refresh our home page and check off one of the items 111 09:58.580 --> 10:03.650 and now you can see I've got the ID of that item. 112 10:03.650 --> 10:10.610 So once I've got the ID then everything else is so much easier because we can now delete the item with 113 10:10.610 --> 10:12.200 that particular ID. 114 10:13.970 --> 10:20.210 Inside our app.js instead of console logging this, I'm going to bind it to a constant and it's 115 10:20.210 --> 10:28.660 going to be called the checkedItemId and it's just going to equal req.body.checkbox. 116 10:28.860 --> 10:37.400 And now as a challenge I want you to remove the item from the database that has the ID of the one that 117 10:37.400 --> 10:42.530 was checked off. Again as a reminder, in the Mongoose documentation 118 10:42.560 --> 10:47.420 you can find a method called findByIdAndRemove 119 10:47.570 --> 10:50.450 which seems pretty much like what we need to do. 120 10:50.480 --> 10:58.040 So in this case we simply provide the ID as an argument and then we have a callback to handle any errors 121 10:58.100 --> 11:00.090 or log success. 122 11:00.350 --> 11:05.900 And when this is executed, it should delete that document with that particular ID. 123 11:06.840 --> 11:11.730 Pause the video and try to complete the challenge. 124 11:11.730 --> 11:15.750 All right. So let's do that right here where we've got access to that ID. 125 11:16.020 --> 11:25.020 I'm going to tap into the items collection using that item model and then I'm going to call 126 11:25.080 --> 11:31.260 findByIdAndRemove. And make sure that you don't have any typos in there. 127 11:31.560 --> 11:38.250 And then the ID is of course going to be the checkedItemId and then we're going to provide that callback 128 11:38.850 --> 11:46.590 to see if there were any errors. And if there were no errors then in that case we're simply going to 129 11:46.620 --> 11:56.220 log that we "Successfully deleted checked item". 130 11:56.240 --> 12:04.610 Now if we check the Mongoose API documentation and you locate the findByIdAndRemove method, if you 131 12:04.610 --> 12:13.320 read through it ill tell you that if you don't provide the callback it won't actually execute the delete. 132 12:13.340 --> 12:16.990 It's only when the callback is there does it actually execute it. 133 12:17.180 --> 12:21.610 Whereas if it only has an ID or option, then it'll just return the query. 134 12:21.610 --> 12:24.480 It'll just find that item by ID. 135 12:24.710 --> 12:29.870 So in order to get the and remove part,we have to provide the callback 136 12:29.870 --> 12:36.740 even if you don't care to check if there were any errors or not. Let's hit save and let's go back to 137 12:36.740 --> 12:40.990 our root route and try to delete one of these items. 138 12:41.030 --> 12:49.850 Again our web interface is not updating but if you go over to the console it says that it successfully 139 12:49.880 --> 12:55.850 deleted the checked item which means that it's probably been deleted 140 12:56.000 --> 13:03.500 and if we again check our Mongo shell and we do "db.items.find" then indeed that item that 141 13:03.500 --> 13:12.800 we just checked off here hit this to delete an item no longer exists in our items collection. 142 13:12.800 --> 13:20.150 But in order for it to reflect in our web page then again we have to call a redirect right? We can say 143 13:20.160 --> 13:24.440 res.redirect to the home route. 144 13:24.800 --> 13:32.060 And now it will find all of the items that we still have in our items collection and render it on the 145 13:32.060 --> 13:33.170 page. 146 13:33.740 --> 13:40.230 So now let's go back to our home page and let's delete some of these random ones 147 13:40.340 --> 13:44.890 then you can see that they're all just getting crossed off and deleted. 148 13:46.370 --> 13:47.090 Pretty neat right?