Coding

#15 Adding a Modal | Build a Complete App with GraphQL, Node.js, MongoDB and React.js

  • 00:00:01 in the last video we worked on
  • 00:00:03 authentication we'll finish this up in
  • 00:00:05 this video when we add logout and
  • 00:00:08 thereafter we'll start working on events
  • 00:00:11 and make sure that we can create events
  • 00:00:13 by in this video adding a modal which
  • 00:00:16 we'll use to hold the form for adding
  • 00:00:18 events so let's dive in
  • 00:00:23 so in the last videos we implemented
  • 00:00:26 authentication and if you followed along
  • 00:00:28 you will notice that the styling is a
  • 00:00:30 little different
  • 00:00:31 I really wasn't happy with the colors I
  • 00:00:33 picked before I did this was recording
  • 00:00:36 now I took some time chose a little bit
  • 00:00:38 some nicer colors here in my opinion and
  • 00:00:40 in the video description below the video
  • 00:00:42 you of course find a link to get up
  • 00:00:44 repository armed with this which is the
  • 00:00:47 entire code just with these colors here
  • 00:00:50 so that is one thing here this now looks
  • 00:00:54 nicer and besides that it's the same as
  • 00:00:57 before and hence we can also still log
  • 00:01:00 in here for example with our credentials
  • 00:01:02 and we are forwarded to this page now in
  • 00:01:05 this video I want to work on the events
  • 00:01:08 I want to start working on that but I
  • 00:01:09 also want to make sure that we can log
  • 00:01:11 out because that's a functionality which
  • 00:01:13 is missing thus far and for dad and the
  • 00:01:15 main navigation I want to add a log out
  • 00:01:18 button of course only if we're locked in
  • 00:01:20 so essentially in this block where I
  • 00:01:22 also render my bookings link there I'll
  • 00:01:25 add a new list item where I want to have
  • 00:01:27 my log out button so I'll add my button
  • 00:01:32 element here and say log out on it and
  • 00:01:35 react doesn't like this if we have two
  • 00:01:38 adjacent elements in one block where we
  • 00:01:43 must return only one element so you
  • 00:01:45 could wrap this in a diff but that would
  • 00:01:47 be a semantically incorrect and
  • 00:01:49 unordered list
  • 00:01:50 so I will actually use react fragment
  • 00:01:53 which is basically an empty react
  • 00:01:55 component that we can use as a container
  • 00:01:57 so now we have that button in place I
  • 00:02:00 want to make sure that this button also
  • 00:02:02 looks nice and for that we could
  • 00:02:06 actually give it the style we have on
  • 00:02:08 all the links here and for that here in
  • 00:02:11 this CSS file I'll add another rule for
  • 00:02:14 main navigation items any buttons that
  • 00:02:17 have I have in there should have the
  • 00:02:18 same styles as my links I will remove
  • 00:02:22 any border I might have there though set
  • 00:02:25 the font to inherit to use my default
  • 00:02:27 font set the background to transparent
  • 00:02:30 and one other thing which is important
  • 00:02:32 set the cursor to pointer so that our
  • 00:02:34 mouse mouse cursor updates
  • 00:02:37 correctly well and then down there I
  • 00:02:39 also want to add my rules for buttons
  • 00:02:43 where I hover over or my buttons where I
  • 00:02:46 which are active and of course you could
  • 00:02:48 use different styles but I'll just use
  • 00:02:50 the same styles as I use on my links so
  • 00:02:55 with that let's quickly sign in again
  • 00:02:59 now the alignment is an issue here we
  • 00:03:02 can fix that and also the padding here
  • 00:03:04 now that I see that or distance we have
  • 00:03:08 between the button here and bookings
  • 00:03:10 let's fix that I'll add a margin of 0 Q
  • 00:03:15 my anchor tags and to my button and on
  • 00:03:17 the or unordered list which surrounds
  • 00:03:20 that all I'll add aligned items since I
  • 00:03:23 use flexbox off-center to align that all
  • 00:03:27 on the same level and now this looks
  • 00:03:29 better to me ok perfect so we have that
  • 00:03:33 now let's make sure that the logout
  • 00:03:34 button also works and for this on this
  • 00:03:37 button I'll add on click equals and then
  • 00:03:42 here I want to execute a method which
  • 00:03:44 well does log us out and we do have our
  • 00:03:47 off context here right and we do added
  • 00:03:51 such that I can access by context there
  • 00:03:53 now all my context I already prepared
  • 00:03:56 this logout method and in Apps is where
  • 00:04:00 we set up this context I also set up a
  • 00:04:03 log art method already which should do
  • 00:04:05 everything I need to do so the remaining
  • 00:04:07 thing is that in the main navigation I
  • 00:04:09 use this context and call log out there
  • 00:04:13 and I don't call it like this with
  • 00:04:15 parentheses instead I just pass a
  • 00:04:17 reference to this logout method to the
  • 00:04:19 onclicklistener so that when the click
  • 00:04:21 occurs it's executed for me so to say so
  • 00:04:24 back on this page let's log in real
  • 00:04:28 quick here we are and click log out and
  • 00:04:31 I'm locked out and I can log in again
  • 00:04:34 and if I should be on bookings while
  • 00:04:38 logging out I'm redirected or I should
  • 00:04:41 be redirected I'm not I stay on bookings
  • 00:04:43 so that's also something which I want to
  • 00:04:44 change let's quickly change that an app
  • 00:04:48 chess where we set up all these routes
  • 00:04:50 there I am making sure that I redirect
  • 00:04:53 from slash to off and that I redirect
  • 00:04:57 from off to events and so on but if I
  • 00:04:59 don't have a token which means I'm not
  • 00:05:00 authenticated then I'll duplicate this I
  • 00:05:03 want to redirect from bookings to off as
  • 00:05:07 well and of course we could also write
  • 00:05:09 this in a more generic way instead of
  • 00:05:12 covering all the cases individually here
  • 00:05:14 so I could say if I'm not authenticated
  • 00:05:17 then I'll not add a from here instead
  • 00:05:20 I'll always go to off here that's the
  • 00:05:24 idea so I always redirect you off and
  • 00:05:28 I'll just move this to the end or at
  • 00:05:31 least after events so that this route in
  • 00:05:35 case I'm on events has a chance of being
  • 00:05:36 handled first because I want to allow
  • 00:05:38 access to events but for all other cases
  • 00:05:41 I want to redirect so let's try if that
  • 00:05:45 works the way it should if I go to
  • 00:05:46 events I can go there if I now do login
  • 00:05:50 and I'm on events and I log out I stay
  • 00:05:55 on events but if I log in again here and
  • 00:06:02 I'm on bookings and log out I'm
  • 00:06:04 redirected to off so this is working but
  • 00:06:07 this is actually not even what I want to
  • 00:06:09 focus on in this video instead let's
  • 00:06:12 work on the events now now on the events
  • 00:06:15 here my goal is that we're able to
  • 00:06:17 create new events and that we then can
  • 00:06:19 see the events we created for that let's
  • 00:06:22 briefly have a look at our schema again
  • 00:06:24 to understand how we create events we do
  • 00:06:27 that by sending a mutation to create
  • 00:06:29 event of course and we do pass our event
  • 00:06:31 input and event input happens to be an
  • 00:06:35 object with a title a description a
  • 00:06:37 price and a date and the date has to be
  • 00:06:39 a string here when we submit that so on
  • 00:06:43 our events page we're currently only
  • 00:06:46 schody of the events page I want to give
  • 00:06:49 the user a button that allows the user
  • 00:06:52 to create a new event for this I'll
  • 00:06:56 render a div here and in that death
  • 00:06:59 let's render a button create event
  • 00:07:05 which if I save that looks like this now
  • 00:07:11 that's nice let's give it some basic
  • 00:07:14 styling at least and for that I want to
  • 00:07:16 reuse the styling of the buttons I had
  • 00:07:18 in my off file so therefore let's
  • 00:07:21 actually grab these styles here in form
  • 00:07:24 actions button and so on and let's grab
  • 00:07:26 all these form controls here and let's
  • 00:07:30 outsource these in a global styling file
  • 00:07:32 which which would be the index CSS file
  • 00:07:34 so that application wide I can have
  • 00:07:36 these styles and of course I wrap my
  • 00:07:40 button here in form actions well I'll
  • 00:07:44 simply add an additional selector and
  • 00:07:45 make sure that not just buttons and form
  • 00:07:47 actions look that way but all the
  • 00:07:49 buttons that have the BTN class and
  • 00:07:51 therefore down there I'll look for BTN
  • 00:07:54 hover and BTN active and this allows me
  • 00:07:58 to add that BTN class to this button
  • 00:08:00 here so class name BTN and by just
  • 00:08:04 adding this well we have this button
  • 00:08:06 which looks a lot nicer obviously now I
  • 00:08:08 want to Center it as well so in my
  • 00:08:11 events page here I'll give this div here
  • 00:08:16 a class of event or events control and
  • 00:08:23 I'll add an event start CSS file where I
  • 00:08:27 want to style that so events control is
  • 00:08:29 my death there I'll add
  • 00:08:32 text-align:center to align that button
  • 00:08:34 in the center but I'll also give this a
  • 00:08:37 border of one pixel solid and now I'll
  • 00:08:41 reuse that color I used for my button
  • 00:08:44 this one this purple color here and
  • 00:08:47 assign that for the border and a padding
  • 00:08:51 of let's say free REM and a margin of QM
  • 00:08:55 top and bottom and auto left right and
  • 00:08:58 the width of 30 REM with a max width of
  • 00:09:02 80% here these are my styles for the
  • 00:09:06 events control for these to apply here I
  • 00:09:10 of course need to import that events dot
  • 00:09:12 CSS file and now as this reloads or
  • 00:09:16 refreshes this is
  • 00:09:18 looks like this is my control area um a
  • 00:09:21 little bit less padding would probably
  • 00:09:24 look good so lets me reduce the reading
  • 00:09:26 heading to one room and now here I'll be
  • 00:09:29 able to create a new event with that
  • 00:09:32 button now I'll also add a paragraph
  • 00:09:35 above that share your own events
  • 00:09:40 something like that okay so now we can
  • 00:09:43 click that button but this button you
  • 00:09:45 guessed it will not do much for creating
  • 00:09:48 an event we could of course open a new
  • 00:09:51 page on our screen here or what I'll do
  • 00:09:55 we can use a modal and for this let's
  • 00:09:58 create a new component in a new folder
  • 00:10:00 which I'll name modal and in there I'll
  • 00:10:02 have my modal J's file now I'll create a
  • 00:10:06 new constant modal which receives props
  • 00:10:09 and which should in the end return the
  • 00:10:13 modal content we need to import react
  • 00:10:16 from react for this and at the bottom
  • 00:10:19 I'll export this as my default modal or
  • 00:10:24 that's the default for this file now in
  • 00:10:27 here let's just render some J's Xcode
  • 00:10:30 that could well basically reflect our
  • 00:10:32 modal I'll have a div and now in that
  • 00:10:35 modal I would have an area for for the
  • 00:10:37 title I want to have my content and I
  • 00:10:39 want to have some action items at the
  • 00:10:41 bottom so in the div here I'll have a
  • 00:10:44 couple of sections or actually a header
  • 00:10:48 for my modal title which of course
  • 00:10:52 should be settle from outside so instead
  • 00:10:54 of hard-coding it let's set props title
  • 00:10:57 here I want to have a Content now here I
  • 00:11:01 can add a section with a class name of
  • 00:11:06 modal content like this and I also want
  • 00:11:12 to have another section with a class
  • 00:11:13 name of modal actions and that will hold
  • 00:11:18 my the buttons where I can control this
  • 00:11:20 modal now you can build a model in 1,000
  • 00:11:24 different ways in all kinds of
  • 00:11:27 variations you can build a very flexible
  • 00:11:29 a modal where you can pass
  • 00:11:31 configure everything here I'll try to
  • 00:11:34 find them some middle ground I'd say for
  • 00:11:38 the content here in the modal I want you
  • 00:11:42 allow you to pass it in from outside so
  • 00:11:45 here I will render props children which
  • 00:11:47 is basically the slot solution react
  • 00:11:51 offers so we can pass anything between
  • 00:11:54 our modal JSX tags later and that will
  • 00:11:57 be rendered into the modal for reactions
  • 00:12:00 I'll have exactly two buttons I'll have
  • 00:12:04 a button which allows me to cancel and a
  • 00:12:08 button which allows me to confirm and
  • 00:12:10 obviously you could make this more con
  • 00:12:12 configurable to the only thing that I
  • 00:12:17 will allow the user to configure is I
  • 00:12:19 will accept props here props can cancel
  • 00:12:24 if data set the cancel button will be
  • 00:12:27 rendered and props can confirm if that
  • 00:12:32 is rendered or if that is set the
  • 00:12:34 confirm button will be rendered that is
  • 00:12:37 my take on that now the buttons will
  • 00:12:40 receive my button styles so I'll give
  • 00:12:42 this class name equal BTN and the modal
  • 00:12:47 as a whole here will receive a class
  • 00:12:48 name of modal with that let's add a
  • 00:12:51 modal CSS file next to the modal J's
  • 00:12:53 here and import modal CSS into the modal
  • 00:12:58 J's file and in modal CSS I of course
  • 00:13:01 want to set the styling for my modal now
  • 00:13:04 this styling is something you can of
  • 00:13:06 course adjust to your requirements and
  • 00:13:08 wishes I'll give my model a width of
  • 00:13:10 let's say 40 M or 50 R m though it will
  • 00:13:14 have a max width of 90% of the available
  • 00:13:18 page size it will have a background of
  • 00:13:22 white so about a white background color
  • 00:13:25 and it'll have a box shadow of 0 2
  • 00:13:28 pixels 8 pixels and then this light
  • 00:13:33 slightly transparent black color here
  • 00:13:38 so that's the modal container or so to
  • 00:13:40 say I also want to position that and it
  • 00:13:44 will have a fixed positioning on the
  • 00:13:46 page and from the top let's say it'll
  • 00:13:49 have a distance of let's say 20 VH that
  • 00:13:53 is a relatively modern unit in CSS and
  • 00:13:57 it stands for a viewport height so 20%
  • 00:13:59 of the viewport browser support is
  • 00:14:01 pretty good right now for this unit so
  • 00:14:03 we can use it here and from the left I
  • 00:14:07 now have a problem because I don't know
  • 00:14:10 the exact width whether it's 90% or this
  • 00:14:13 so I will actually define a two rules
  • 00:14:17 here I will have a width of 90% as a
  • 00:14:21 default and then I'll add a media query
  • 00:14:24 for bigger screens because that is meant
  • 00:14:27 for smaller screens so a media query
  • 00:14:30 where I will check that we have a min
  • 00:14:35 width of let's say 768 pixels and if
  • 00:14:39 that is the case
  • 00:14:40 I'll override my modal rule and they're
  • 00:14:43 set to with – yeah maybe 50 M and then
  • 00:14:49 up here I can set left to 5% because I
  • 00:14:53 have 90% with I divided the remaining
  • 00:14:56 part between the left and right side and
  • 00:14:58 down there I know I have a width of 50 R
  • 00:15:01 M so I can calculate the left distance
  • 00:15:05 by using 100% of the screen size of the
  • 00:15:08 of the page width so to say – 50 R M and
  • 00:15:16 that should now be divided by 2
  • 00:15:23 now let's add that modal on our events
  • 00:15:26 jazz page just so that we can see it for
  • 00:15:30 this I'll wrap this all in a react
  • 00:15:31 fragment and then I'll add the modal by
  • 00:15:34 just adding it's a JSX
  • 00:15:37 selector here so import modal from
  • 00:15:42 components modal modal and we could use
  • 00:15:45 react portal for that I'll just
  • 00:15:47 implement it like this and add my molar
  • 00:15:50 here with my modal content which again
  • 00:15:53 is passed between the opening and
  • 00:15:55 closing tags so this is my modal looks
  • 00:15:58 centered to me now on smaller screens
  • 00:16:01 this also looks good so we can take this
  • 00:16:05 I guess now of course I'm not done with
  • 00:16:08 the modal well first of all I think it's
  • 00:16:10 too big but that's a minor thing I think
  • 00:16:12 30 Ram will do so let's use 30 Ram down
  • 00:16:16 there as well but the most important
  • 00:16:18 thing is I'm not done with the styling I
  • 00:16:21 have my modal header I have my modal
  • 00:16:23 content I'll give my modal header here a
  • 00:16:25 class of modal header because I want to
  • 00:16:28 select that by a class two and I'll then
  • 00:16:31 add modal header here now in the modal
  • 00:16:35 header I'll have a padding of a 1 R M
  • 00:16:38 and I'll add a background of my purple
  • 00:16:43 color which I used before so let me grab
  • 00:16:45 that purple color and yes of course we
  • 00:16:48 could use SAS or anything like that but
  • 00:16:50 I'll just do it with vanilla CSS and set
  • 00:16:54 the text color to white in there and
  • 00:16:56 then in my header here the props title
  • 00:17:00 will actually be inside of a h1 tag
  • 00:17:04 let's say and therefore in the CSS code
  • 00:17:08 I want to make sure that this h1 tag in
  • 00:17:10 the modal header has no extra margin
  • 00:17:13 because I already set a padding and I'll
  • 00:17:15 set the font size to let's say 1.25 rep
  • 00:17:19 so that's the malt modal header the
  • 00:17:22 modal content will have the padding of 1
  • 00:17:26 R M and that's it basically the rest is
  • 00:17:29 passed in from outside and for my modal
  • 00:17:32 actions where well they're all set this
  • 00:17:34 to display flex
  • 00:17:36 and then justify content to flex and to
  • 00:17:38 move them to the end of my mode now in
  • 00:17:42 events where I use the modal let's also
  • 00:17:45 set some props to configure it correctly
  • 00:17:48 set the title for example to add event
  • 00:17:52 set D let me quickly have a look at the
  • 00:17:56 modal the can cancel and can confirm
  • 00:17:59 props so can cancel and can confirm like
  • 00:18:03 this will be treated as true and if we
  • 00:18:05 go back we therefore see our buttons
  • 00:18:07 some spacing at the bottom would be nice
  • 00:18:09 so in the modal here on my actions I'll
  • 00:18:15 also add a padding of one room around
  • 00:18:17 that safe this yeah looks good now
  • 00:18:21 obviously our modal also needs a
  • 00:18:23 backdrop behind it on the page and I
  • 00:18:26 will create that separately in a new
  • 00:18:28 folder the backdrop backdrop j/s and
  • 00:18:31 there will be a very simple component
  • 00:18:34 this backdrop here in the end this is
  • 00:18:38 just a div here which I'll give a class
  • 00:18:43 name of backdrop and which will now
  • 00:18:45 receive some styling obviously we need
  • 00:18:48 to import react from react here too and
  • 00:18:51 we then need to export the backdrop as a
  • 00:18:56 default so that is the backdrop let's
  • 00:19:01 now add the backdrop CSS file to add the
  • 00:19:04 styles for the backdrop and here for the
  • 00:19:07 stalls I want to have a position of
  • 00:19:11 fixed top should be zero left should be
  • 00:19:15 zero height should be 100 VH to take the
  • 00:19:19 full height of the viewport width will
  • 00:19:21 be 100% and the background color will be
  • 00:19:28 slightly transparent black color a less
  • 00:19:33 transparent than the shadow of the modal
  • 00:19:35 though now let's use that backdrop on
  • 00:19:37 the events page as well so for this
  • 00:19:40 I'll not just import the modal but also
  • 00:19:43 the backdrop from components backdrop
  • 00:19:48 backdrop
  • 00:19:49 and for now I'll just drop it in there
  • 00:19:51 my backdrop like this and if we go back
  • 00:19:55 nothing happens because in my backdrop
  • 00:20:00 J's file I of course need to import the
  • 00:20:02 backdrop CSS file otherwise we see no
  • 00:20:05 styling but now we got a backdrop so
  • 00:20:07 this is now the modal this is how it
  • 00:20:09 will look like I want to open that modal
  • 00:20:14 when I click create event of course and
  • 00:20:16 I will manage this flow here in events J
  • 00:20:22 s by adding an onclicklistener to this
  • 00:20:31 create event button and I extend my
  • 00:20:36 component so I use the class based
  • 00:20:38 approach and hence I can manage state
  • 00:20:40 here and in that state we could have a
  • 00:20:45 creating property which initially is
  • 00:20:47 false and we can then add a method
  • 00:20:51 create event handler or a start create
  • 00:20:57 event handler to be very descriptive of
  • 00:20:59 what's happening and in there all I call
  • 00:21:03 this set state and set creating to true
  • 00:21:06 and that will be my trigger for showing
  • 00:21:08 or hiding dead bactrim intermodal so I
  • 00:21:12 will now wrap this year with conditional
  • 00:21:16 statements and check if this state
  • 00:21:18 creating is true if it is then I will
  • 00:21:20 render this backdrop so and backdrop and
  • 00:21:24 the same for the modal here I can check
  • 00:21:27 if this state creating is true and if it
  • 00:21:30 is with the shortcut in there and
  • 00:21:31 percent signs of the boolean and
  • 00:21:33 connector arm I can render both the
  • 00:21:37 backdrop at the modal I got an error
  • 00:21:40 down there
  • 00:21:43 yeah obviously I should assign my click
  • 00:21:46 listener so this should point at start
  • 00:21:48 create event handler so is there we can
  • 00:21:51 save this and if I now click create
  • 00:21:53 event we open this which is awesome
  • 00:21:56 now I want to close it when I click
  • 00:21:58 cancel or confirm and for this in the
  • 00:22:01 modal I need to add some event listeners
  • 00:22:03 to my buttons so when I click the cancel
  • 00:22:06 button I want to trigger a method or a
  • 00:22:10 function which is received on a prop and
  • 00:22:13 the prop will be named on cancel but you
  • 00:22:15 could name it whatever you want and use
  • 00:22:17 this uses the classic way of executing
  • 00:22:21 functions across components and react
  • 00:22:23 where we receive a handle to the
  • 00:22:26 function of reference to a function in a
  • 00:22:28 component through props and then we can
  • 00:22:30 call a function that lives in another
  • 00:22:32 component in yet another component
  • 00:22:35 because of that connection through props
  • 00:22:37 and that's what I establish here I'll
  • 00:22:39 add my own to props on cancel and on
  • 00:22:43 confirm and I can't pass in function
  • 00:22:46 references on these properties so now in
  • 00:22:49 the events JS file here on my modal I
  • 00:22:52 can simply add on cancel here and on
  • 00:22:58 confirm and execute some methods in this
  • 00:23:01 events page and there I'll have my modal
  • 00:23:06 confirm Handler and my modal cancel
  • 00:23:15 handler method in that class now in the
  • 00:23:19 modal cancel handler I'll call set state
  • 00:23:21 and set creating to false and for now
  • 00:23:26 that's also the only thing I'll do here
  • 00:23:28 though later in the modal confirm
  • 00:23:30 handler I want to basically gather all
  • 00:23:32 the values I entered for a new event and
  • 00:23:34 output these so now let's bind this year
  • 00:23:40 to the modal cancel handler and then
  • 00:23:44 this on confirm prop will receive the
  • 00:23:46 modal confirm handler and now with that
  • 00:23:49 setup we can go back and we can now open
  • 00:23:52 that modal and close it through cancel
  • 00:23:55 and confirm now that
  • 00:23:57 all amazing but obviously we still can't
  • 00:24:01 enter anything so in the next video
  • 00:24:03 we'll now finally get started with that
  • 00:24:06 and make sure that we can create a new
  • 00:24:08 event