1 00:00:00,360 --> 00:00:03,450 All right, let's get into the meat of our application. 2 00:00:03,450 --> 00:00:06,690 Let's allow students who we know to submit ideas, and 3 00:00:06,690 --> 00:00:08,360 then we'll display them in a list. 4 00:00:10,500 --> 00:00:13,240 How are we gonna make sure that we know the student? 5 00:00:13,240 --> 00:00:16,440 I know, let's expose a link in our if statement that 6 00:00:16,440 --> 00:00:17,979 checks if we know their username. 7 00:00:19,170 --> 00:00:23,710 Okay, so let's start out by opening up our index.hbs page. 8 00:00:23,710 --> 00:00:26,850 So that's this guy here, index.hbs. 9 00:00:26,850 --> 00:00:30,294 And I'm going to get rid of this TODO because we TO-DID that. 10 00:00:30,294 --> 00:00:35,343 And so inside the if block here, we want to add a hyperlink and 11 00:00:35,343 --> 00:00:39,113 a hyperlink will do that using an anchor tag. 12 00:00:39,113 --> 00:00:43,867 So let's make a new paragraph here, and we'll say View and if I do a and 13 00:00:43,867 --> 00:00:46,606 then I do a Tab, it's gonna build out and 14 00:00:46,606 --> 00:00:50,500 that href there is the reference of where we want it to go. 15 00:00:50,500 --> 00:00:53,940 So we want it to go to /ideas, which we havent built yet, but we will. 16 00:00:55,080 --> 00:00:59,010 And we'll make it say View all course ideas. 17 00:00:59,010 --> 00:01:01,490 And that makes that a link, right? 18 00:01:01,490 --> 00:01:07,280 So when you click all course ideas, it will make a get request to /ideas. 19 00:01:07,280 --> 00:01:08,790 So we better catch that, right? 20 00:01:08,790 --> 00:01:10,460 So let's flip over back to main.Java. 21 00:01:13,040 --> 00:01:17,940 Let's add a new get, and we'll say get ideas. 22 00:01:19,370 --> 00:01:23,520 And that of course gets our request and response object route. 23 00:01:24,770 --> 00:01:27,465 We know it's gonna be a multi-liner. 24 00:01:27,465 --> 00:01:31,870 And we know that it's gonna take the new HandlebarsTemplateEngine. 25 00:01:35,240 --> 00:01:35,740 Okay. 26 00:01:37,115 --> 00:01:42,710 Why don't we just pop our ideas into the model context, right? 27 00:01:42,710 --> 00:01:45,500 Now obviously at first there won't be any but that's okay. 28 00:01:45,500 --> 00:01:46,590 Let's do it. 29 00:01:46,590 --> 00:01:48,305 So we'll make a new model. 30 00:01:48,305 --> 00:01:51,425 [BLANK] Yeah, 31 00:01:51,425 --> 00:01:57,180 that of course is a HashMap. 32 00:01:57,180 --> 00:01:58,259 It's getting repetitive, isn't it? 33 00:02:01,656 --> 00:02:03,663 Sure wish that that auto-completed. 34 00:02:03,663 --> 00:02:05,210 There's probably a way to do that. 35 00:02:06,350 --> 00:02:13,700 Okay, so inside the model, let's put our ideas, a collection of ideas. 36 00:02:13,700 --> 00:02:17,310 And now we have access to our data access object. 37 00:02:17,310 --> 00:02:20,360 And remember, we made one called findAll, 38 00:02:20,360 --> 00:02:23,870 and our implementation returns a copy of the list. 39 00:02:23,870 --> 00:02:24,390 Cool. 40 00:02:24,390 --> 00:02:27,791 Sorry, we don't want String String on this one, we actually want String object. 41 00:02:32,199 --> 00:02:36,542 Okay, and we're going to return new ModelAndView, 42 00:02:36,542 --> 00:02:39,533 and we're gonna return the model and 43 00:02:39,533 --> 00:02:45,050 we're gonna have that go to our ideas page that doesn't yet exist. 44 00:02:45,050 --> 00:02:45,840 So, let's go make that. 45 00:02:47,040 --> 00:02:53,670 So, we'll make a new ideas.hbs file. 46 00:02:53,670 --> 00:02:57,200 Okay, and we want to first say what we're gonna inherit from. 47 00:02:57,200 --> 00:02:59,184 Let's inherit from base.hbs. 48 00:03:00,570 --> 00:03:04,550 Now that that's out of the way we can add our new partial at the top. 49 00:03:06,510 --> 00:03:08,620 We want this to be the partial for content. 50 00:03:10,810 --> 00:03:11,570 Great. 51 00:03:11,570 --> 00:03:15,050 Okay, so we know that this is the idea page so that's a good heading, right? 52 00:03:15,050 --> 00:03:17,830 So, let's say Current Ideas. 53 00:03:20,250 --> 00:03:24,150 So in HTML when you want to display a list you actually have a few options. 54 00:03:24,150 --> 00:03:28,945 So one of the most obvious ones to use first is an unordered list, 55 00:03:28,945 --> 00:03:29,930 and that's a ul. 56 00:03:29,930 --> 00:03:35,720 So you type ul and each one of those has a thing called an li which is a list item. 57 00:03:35,720 --> 00:03:39,160 So what we want to do is we want to loop through each of the ideas and 58 00:03:39,160 --> 00:03:40,510 make a list item. 59 00:03:40,510 --> 00:03:44,630 So in order to do that Handle Bars has a really nice block helper and 60 00:03:44,630 --> 00:03:45,950 it's called each. 61 00:03:45,950 --> 00:03:48,370 You can kind of imagine this as doing a for each loop. 62 00:03:48,370 --> 00:03:52,960 So we're gonna say, #each, and then you loop on the object. 63 00:03:52,960 --> 00:03:55,680 Now remember when we pushed ideas into the context, so 64 00:03:55,680 --> 00:03:57,680 we're gonna loop through each idea. 65 00:03:59,620 --> 00:04:03,190 So basically this is saying for each idea in ideas. 66 00:04:03,190 --> 00:04:04,744 And we'll add a new li. 67 00:04:06,654 --> 00:04:10,880 Or list item for each of those ideas and now this is a little bit different. 68 00:04:10,880 --> 00:04:16,974 Inside this each loop, it's the block scope is against the idea. 69 00:04:16,974 --> 00:04:21,020 So actually all we want to do here is we want to show the title, right? 70 00:04:21,020 --> 00:04:22,920 So we're going to show the title of the idea. 71 00:04:25,570 --> 00:04:28,430 Now wait a second, how does it know about the word title? 72 00:04:28,430 --> 00:04:34,140 The course idea object, if we take a look at that, it only has getTitle, right? 73 00:04:34,140 --> 00:04:37,940 This is a private thing so it can't see that, so it only sees this getTitle. 74 00:04:37,940 --> 00:04:42,730 So the handlebars.java implementation understands POJO, or 75 00:04:42,730 --> 00:04:45,590 plain old java object syntax. 76 00:04:45,590 --> 00:04:48,600 So it knows that it can call the getTitle method on our object. 77 00:04:48,600 --> 00:04:50,970 It's pretty cool, right? 78 00:04:50,970 --> 00:04:53,440 So, we didn't need to write getTitle here. 79 00:04:53,440 --> 00:04:55,408 We just wrote title and it pulled it out. 80 00:04:58,695 --> 00:05:01,060 Okay, so let's walk that one more time. 81 00:05:01,060 --> 00:05:05,740 So, we passed in a list of course ideas into our model context, 82 00:05:05,740 --> 00:05:07,350 right, for model and view. 83 00:05:07,350 --> 00:05:10,880 And then, there's a block helper and it's called each. 84 00:05:12,940 --> 00:05:16,750 It works with each item in this list. 85 00:05:16,750 --> 00:05:21,210 For each of those items, it puts it into this block's scope. 86 00:05:21,210 --> 00:05:23,660 In here, this block's scope is that item. 87 00:05:25,170 --> 00:05:31,240 And it pushed in a course idea object, which has a method called getTitle, 88 00:05:31,240 --> 00:05:34,176 and it can be accessed here by not putting the get prefix. 89 00:05:34,176 --> 00:05:36,762 Make sense? 90 00:05:36,762 --> 00:05:37,912 Okay. 91 00:05:37,912 --> 00:05:42,400 So now after that each, let's go ahead and let's add a form to add a new one. 92 00:05:44,950 --> 00:05:50,710 So, let's make it post to the same page, to ideas, right? 93 00:05:50,710 --> 00:05:52,310 But we want it to post, right? 94 00:05:52,310 --> 00:05:54,310 Cuz we're adding information. 95 00:05:55,460 --> 00:05:55,960 Okay. 96 00:05:57,000 --> 00:06:01,260 Inside this form let's 97 00:06:01,260 --> 00:06:06,159 have a field called title. 98 00:06:06,159 --> 00:06:12,506 Let's make the placeholder say "What's your idea? 99 00:06:12,506 --> 00:06:14,884 And we're gonna name that title so 100 00:06:14,884 --> 00:06:18,960 when it comes across it will be title in the query string. 101 00:06:18,960 --> 00:06:19,690 All right. 102 00:06:19,690 --> 00:06:25,340 And then let's make a button that says Suggest. 103 00:06:27,380 --> 00:06:32,120 So clicking that button will submit this form via post to ideas. 104 00:06:33,170 --> 00:06:34,780 So we better go catch that, right? 105 00:06:36,170 --> 00:06:41,284 So let's go back to Main, and we already have one for 106 00:06:41,284 --> 00:06:47,228 ideas here, but we can also do a post version to the same URI. 107 00:06:49,896 --> 00:06:53,190 So we'll do req and res. 108 00:06:57,180 --> 00:06:59,980 Okay, so let's pull the title from the form submission. 109 00:06:59,980 --> 00:07:01,500 So we wanna get a title out. 110 00:07:01,500 --> 00:07:06,566 So the title is going 111 00:07:06,566 --> 00:07:13,150 to be req.queryParams. 112 00:07:13,150 --> 00:07:15,170 And we named that field "title". 113 00:07:15,170 --> 00:07:21,790 Great, okay, so now we have the title, and let's make a new course idea. 114 00:07:21,790 --> 00:07:24,650 We'll use the title and then we'll pull the username from the cookie. 115 00:07:26,620 --> 00:07:30,905 Okay, so we'll say new 116 00:07:30,905 --> 00:07:36,710 CourseIdea = new CourseIdea. 117 00:07:36,710 --> 00:07:37,850 No, not course idea. 118 00:07:37,850 --> 00:07:43,633 Let's go ahead and say that it's that, and we want to pass on the title and 119 00:07:43,633 --> 00:07:49,560 it takes a title and it takes a username. 120 00:07:49,560 --> 00:07:50,840 So we'll pull that from the cookie. 121 00:07:53,430 --> 00:07:55,040 It's a little interesting, right? 122 00:07:55,040 --> 00:07:59,230 We're binding our implementation detail to the fact that it's using a cookie. 123 00:07:59,230 --> 00:08:01,050 What if we wanted to change that later? 124 00:08:01,050 --> 00:08:02,930 What I'm gonna do, I'm gonna leave a TODO here, 125 00:08:02,930 --> 00:08:04,700 because that feels a little awkward doesn't it? 126 00:08:04,700 --> 00:08:08,230 It feels like the only way that we know who's logged in is by a cookie. 127 00:08:09,570 --> 00:08:14,630 We don't wanna expect that, so let's leave it the TODO here and csd is my initials. 128 00:08:14,630 --> 00:08:20,530 So, this username is tied to the cookie implementation. 129 00:08:20,530 --> 00:08:21,380 That's not good stuff. 130 00:08:21,380 --> 00:08:22,190 We wanna fix that. 131 00:08:23,200 --> 00:08:27,200 Okay, and our data access objects exposed a method that lets us add. 132 00:08:27,200 --> 00:08:28,500 We should probably use it, right? 133 00:08:28,500 --> 00:08:35,400 So, the data access object add(courseIdea). 134 00:08:35,400 --> 00:08:40,040 Now we could show a page that says it was added but that seems kinda silly, right? 135 00:08:40,040 --> 00:08:43,990 What should happen is that the user should just see their idea on the list, right? 136 00:08:43,990 --> 00:08:45,070 But we can do this. 137 00:08:45,070 --> 00:08:49,160 Why don't we just refresh the ideas page and it should just show up, right? 138 00:08:49,160 --> 00:08:51,874 Because we added it and before in the get we lifted them all so 139 00:08:51,874 --> 00:08:53,670 it should just show up. 140 00:08:53,670 --> 00:08:55,860 So this is known as redirection. 141 00:08:55,860 --> 00:09:00,360 What we'll do is we'll redirect the client to the Ideas page 142 00:09:00,360 --> 00:09:02,581 which will hit our get route here. 143 00:09:03,700 --> 00:09:04,260 Cool? 144 00:09:04,260 --> 00:09:05,300 So let's add it. 145 00:09:05,300 --> 00:09:12,950 So, on the response there is a method called redirect and you pass in the URI. 146 00:09:12,950 --> 00:09:16,240 So, redirect it, it's gonna do a get, so it's gonna do a get there. 147 00:09:16,240 --> 00:09:22,154 And we have to return something, so the pattern is that you return null. 148 00:09:22,154 --> 00:09:24,409 Okay, what do you say we give that a go? 149 00:09:24,409 --> 00:09:25,430 Let's do it. 150 00:09:25,430 --> 00:09:30,309 So I'm going to run my server, restart yours if yours is running, 151 00:09:30,309 --> 00:09:31,712 mine had stopped. 152 00:09:35,621 --> 00:09:41,020 Okay, and I'm gonna flip over here, go to localhost. 153 00:09:41,020 --> 00:09:45,910 I am currently logged in, so we saw that in the if statement. 154 00:09:45,910 --> 00:09:46,590 We can stop that. 155 00:09:46,590 --> 00:09:51,030 Let's bring that up and let's take a look at the resources. 156 00:09:51,030 --> 00:09:52,120 We'll wipe this cookie. 157 00:09:55,040 --> 00:09:57,420 Let's make sure that we don't see the view all course ideas. 158 00:09:57,420 --> 00:09:57,920 Awesome. 159 00:09:59,940 --> 00:10:06,730 Okay, so do, now that we know who's there. 160 00:10:06,730 --> 00:10:08,389 This page is kind of ugly, we need to get rid of this. 161 00:10:09,830 --> 00:10:10,800 Now we can do this. 162 00:10:10,800 --> 00:10:12,270 We can click on View all course ideas. 163 00:10:12,270 --> 00:10:13,976 What's your idea? 164 00:10:13,976 --> 00:10:17,000 I think that we should have one on how to test spark. 165 00:10:17,000 --> 00:10:18,510 So we should do Spark Testing. 166 00:10:18,510 --> 00:10:20,860 Now I had to type that in before, that's why that showed up there. 167 00:10:20,860 --> 00:10:21,800 I'm gonna click Suggest. 168 00:10:23,010 --> 00:10:24,160 Whoa, look at that. 169 00:10:24,160 --> 00:10:25,150 It just showed up. 170 00:10:26,240 --> 00:10:30,920 So again, what happens is we posted and 171 00:10:30,920 --> 00:10:35,560 then the response added it to the list and then it redirected to ideas. 172 00:10:35,560 --> 00:10:38,360 Now, the browser knows how to handle what a redirect is. 173 00:10:38,360 --> 00:10:40,870 It tells the browser to make a new get request. 174 00:10:40,870 --> 00:10:44,020 So, really, what happened here was two request response loops, right? 175 00:10:44,020 --> 00:10:45,690 So, I put in the idea. 176 00:10:45,690 --> 00:10:48,852 So, let's say that I wanted to do a course on 177 00:10:48,852 --> 00:10:57,300 CSS Basics and we click Suggest. 178 00:10:57,300 --> 00:10:59,200 So that's gonna do a post. 179 00:10:59,200 --> 00:11:02,150 And then it's sending the new get, right? 180 00:11:02,150 --> 00:11:07,480 So what this is known as is the post-redirect get pattern or PRG. 181 00:11:07,480 --> 00:11:09,210 More in the teacher's notes. 182 00:11:09,210 --> 00:11:13,520 So remember, this simple course idea, Data Access Objects, we built here, 183 00:11:13,520 --> 00:11:15,120 it only exists in memory. 184 00:11:15,120 --> 00:11:18,460 So if we were to reboot, it would just go away. 185 00:11:18,460 --> 00:11:22,450 But many others at this time could hit this site, and also add their ideas. 186 00:11:22,450 --> 00:11:24,865 One second here, I just got a ping on my messenger. 187 00:11:24,865 --> 00:11:30,150 [LAUGH] Just like I thought, a designer coworker friend of mine walked by my desk, 188 00:11:30,150 --> 00:11:34,050 and saw what we were doing, and sent me a message saying, dude, what is it, the 90s? 189 00:11:34,050 --> 00:11:35,459 Here's some CSS in a better wrapper. 190 00:11:35,459 --> 00:11:37,389 [LAUGH] I love working here. 191 00:11:37,389 --> 00:11:39,290 All right, so he gave me some CSS. 192 00:11:39,290 --> 00:11:43,900 So I'm gonna go ahead, I'm gonna grab the CSS I put in the teacher's notes. 193 00:11:43,900 --> 00:11:49,860 So, if you wanna copy it to your clipboard, which I'm doing right now, 194 00:11:49,860 --> 00:11:54,040 and if we paste that in our main CSS 195 00:11:54,040 --> 00:11:59,220 file and go ahead and save that. 196 00:11:59,220 --> 00:12:01,030 It's a lot of stuff there. 197 00:12:01,030 --> 00:12:03,560 I'm trusting him because I trust my co-workers. 198 00:12:03,560 --> 00:12:07,470 I'm gonna flip over here to my 199 00:12:09,860 --> 00:12:15,530 base page cuz he wants us to add a new wrapper around our page. 200 00:12:15,530 --> 00:12:17,180 And because we have a page wrapper we can do that. 201 00:12:17,180 --> 00:12:19,790 So I'm gonna make a new div which is like a divider or 202 00:12:19,790 --> 00:12:22,040 division a section like thing. 203 00:12:22,040 --> 00:12:29,630 So we're gonna say class = page. 204 00:12:29,630 --> 00:12:32,870 And that div is gonna span all the way across our content. 205 00:12:32,870 --> 00:12:35,600 All right. 206 00:12:35,600 --> 00:12:40,432 So, this is what Sully, my designer friend, wanted us to do, 207 00:12:40,432 --> 00:12:43,274 my coworker, so let's take a look. 208 00:12:43,274 --> 00:12:47,204 Let's go ahead and refresh our page. 209 00:12:47,204 --> 00:12:49,430 Wow, nice. 210 00:12:49,430 --> 00:12:50,900 Look at our ideas. 211 00:12:52,450 --> 00:12:53,030 Much better. 212 00:12:54,060 --> 00:12:56,540 Thank you for bringing us into the current century. 213 00:12:58,010 --> 00:13:00,420 >> Great job getting that list of ideas displayed and 214 00:13:00,420 --> 00:13:02,150 adding a form that updates our data. 215 00:13:02,150 --> 00:13:03,780 This is really starting to come together. 216 00:13:05,050 --> 00:13:09,900 One thing that jumped out to me, is that we blocked unknown users, but 217 00:13:09,900 --> 00:13:13,130 only by not showing them the View All Ideas link. 218 00:13:13,130 --> 00:13:17,130 But the way that the Internet works, anyone can pass a URL around, so 219 00:13:17,130 --> 00:13:20,150 just keeping that link hidden behind an If block 220 00:13:20,150 --> 00:13:21,900 isn't really the best way to protect a page. 221 00:13:23,570 --> 00:13:26,560 You know, now that we learned that redirect trick, 222 00:13:26,560 --> 00:13:29,370 wouldn't it be cool if we didn't have the right credentials, 223 00:13:29,370 --> 00:13:33,450 if we didn't have their username, if we could block them from continuing? 224 00:13:33,450 --> 00:13:35,000 Let's do just that after this break. 225 00:13:36,380 --> 00:13:40,270 I was thinking, do you think you can remove that silly page after sign-in and 226 00:13:40,270 --> 00:13:43,090 just have it redirect to the home page after they submit their username?