- 00:00:01 welcome back to this series where we're
- 00:00:03 going to connect our angle Q or view
- 00:00:06 chess front-end to our level back and
- 00:00:09 see how level and what your view chess
- 00:00:12 can work together now we created our
- 00:00:15 level back end in the last video now
- 00:00:18 it's time to create our angular 2
- 00:00:20 front-end and to connect it I got a
- 00:00:23 brand new angle to application created
- 00:00:26 with the CLI I only removed some content
- 00:00:29 in the app component which we have there
- 00:00:31 by default a daddy dave here with the
- 00:00:34 idea app and stat and then the
- 00:00:36 index.html file I added this import you
- 00:00:39 get bootstrap to get some basic styling
- 00:00:42 now with that what I want to do is I
- 00:00:44 want to start by creating a couple of
- 00:00:47 components so I'll use the CLI for that
- 00:00:49 and generate or just G a new component
- 00:00:53 or just C and then we'll need a quote
- 00:00:57 component for an individual quote in our
- 00:01:00 list of quotes so that's something I'll
- 00:01:03 create then I'm going to create a quotes
- 00:01:06 component holding that list of single
- 00:01:09 quotes and I'll add a new quote
- 00:01:12 component to be able to create a new
- 00:01:15 quote guess what so that gave me those
- 00:01:17 free new folders there I'll quickly
- 00:01:20 remove these spec files could have also
- 00:01:22 just a TC like command but whatever and
- 00:01:25 with that we get our base well skeleton
- 00:01:28 aware the files we need for now let's
- 00:01:31 fill them with some life
- 00:01:32 so in the app component HTML file I want
- 00:01:35 to use the bootstrap grid and for that
- 00:01:39 I'll create a new dev with the class
- 00:01:40 container then row and then call XS 12
- 00:01:44 to have a 12 column broad well column e
- 00:01:50 or I guess a full-screen column
- 00:01:53 basically on all devices on all screen
- 00:01:55 widths and in there I want to place a
- 00:01:59 router outlet that we haven't added the
- 00:02:01 router yet we will do so there soon so
- 00:02:04 this will be the place where I want to
- 00:02:05 render already quotes component with all
- 00:02:08 the quotes or the new quote component
- 00:02:10 and for this to work I'll copy this row
- 00:02:14 here at a horizontal line and in the top
- 00:02:18 row I won't have the router outlet here
- 00:02:20 when I want to have some links instead
- 00:02:22 so here I will have a link which leads
- 00:02:26 to the quotes and one which allows me to
- 00:02:30 add a new quote so to switch between
- 00:02:32 those two pages all set up so there I
- 00:02:35 will add your router links as soon as I
- 00:02:37 created the routes that is my first page
- 00:02:41 here didi app component for now and in
- 00:02:45 the CSS file
- 00:02:46 I also added this app or this this
- 00:02:51 little style here for the wrapping
- 00:02:53 container with the idea of app to give
- 00:02:55 it some margin to not sit on the edges
- 00:02:58 so this is the app and just as a side
- 00:03:00 note I will of course also add the
- 00:03:03 finished app as a download to this
- 00:03:05 project individual description now with
- 00:03:08 this setup let's go to the code
- 00:03:11 component to create a single quote here
- 00:03:14 I'll add the panel class which trip
- 00:03:17 gives me and then also the panel default
- 00:03:20 class to make a default panel to just
- 00:03:23 have this quote well stand out a bit and
- 00:03:25 just have a nice border and so on and in
- 00:03:28 there I'll leave the LED panel body what
- 00:03:31 I want to output the quote content well
- 00:03:34 quote is some object I haven't treated
- 00:03:37 as a property yet but I will do so in a
- 00:03:39 second and I will have a panel body
- 00:03:42 there too now in the panel body and
- 00:03:45 these are all just bootstrap classes
- 00:03:47 keep that in mind
- 00:03:48 in the panel body I want to have a
- 00:03:51 couple of links to added save and so on
- 00:03:54 but I'll come back to this let's work on
- 00:03:57 the quote here I'm referring to some
- 00:04:00 quote property which I haven't added yet
- 00:04:02 and this quote property seems to have a
- 00:04:06 content property so it seems to be an
- 00:04:08 object because it makes sense I guess
- 00:04:11 we're creating quotes each quote will
- 00:04:13 have an ID and a content so why not pack
- 00:04:17 it into an object and for this I will
- 00:04:20 create an interface to have some kind of
- 00:04:22 blueprint of how a quote should look
- 00:04:24 like in my angular 2 application so I'll
- 00:04:26 create this quote
- 00:04:28 face dot typescript file in my root
- 00:04:30 folder and in there I'll simply export
- 00:04:34 not a class an interface which will then
- 00:04:37 quote and here I'll define that I will
- 00:04:40 have a content of type string and an
- 00:04:42 idea of type number that's all this is
- 00:04:44 my quote interface and this now allows
- 00:04:47 me to go to my quote component add this
- 00:04:49 new quote property which will be of type
- 00:04:52 not quote component just of type quote
- 00:04:55 self this newly created interface
- 00:04:57 therefore I also need to add the import
- 00:04:59 up here so this gives me the code object
- 00:05:03 code property here in the individual
- 00:05:05 quote component of course I want to have
- 00:05:08 more than one quote I want to loop
- 00:05:10 through all the quotes so time to go to
- 00:05:12 the quotes plural component here to the
- 00:05:17 template of that component to be precise
- 00:05:19 and use our app quote selector the
- 00:05:22 selector of this single quote component
- 00:05:24 as set up here and loop through it so
- 00:05:28 add an NG for loop do you loop through
- 00:05:31 all the quotes we got here referring to
- 00:05:34 the quotes property which of course I
- 00:05:35 haven't created too so let's add a 2d
- 00:05:39 quotes component here simpler quotes
- 00:05:42 property which is of type quote also add
- 00:05:47 the import here but not a single quote
- 00:05:50 instead a quote array so now the quotes
- 00:05:53 component get a property called quotes
- 00:05:54 holding an array of quotes following our
- 00:05:57 blueprint as setup in the quote
- 00:05:59 interface now if that I can live through
- 00:06:02 all the quotes outputted here and well
- 00:06:07 therefore create a couple of quote
- 00:06:09 components one for each quote we're
- 00:06:11 getting from the server talking of
- 00:06:14 getting well let me also add a
- 00:06:16 horizontal line above the list and a
- 00:06:19 button which will receive the button
- 00:06:21 button primary classes bootstrap classes
- 00:06:24 to get quotes and here I will call a
- 00:06:28 method called on get quotes once you
- 00:06:32 click on it this will allow me to reach
- 00:06:34 out to the server and fetch all the
- 00:06:36 quotes well now with that we get the
- 00:06:40 basic setup for
- 00:06:41 adding quotes and keep in mind we
- 00:06:43 already get one code in our database
- 00:06:45 because we created that quote in the
- 00:06:48 last video when we created the backend
- 00:06:50 so no need to hook up the added delete
- 00:06:53 and cell buttons and the the add new
- 00:06:56 quote page that's not needed instead
- 00:06:58 let's see if that works
- 00:07:01 as it should if we're able to get quotes
- 00:07:03 now for it I will still need to set up
- 00:07:06 the routing though because I already
- 00:07:08 want to set all the pages up as they
- 00:07:10 should be in the end or at least the
- 00:07:11 structure of the pages so add a new file
- 00:07:14 the app dot routing dot TS file and in
- 00:07:18 there I will treat a new constant named
- 00:07:20 app routes this name is up to you which
- 00:07:22 will be of type routes holding all the
- 00:07:25 application routes here and this is just
- 00:07:28 an array of objects as you probably
- 00:07:30 learned in one of my other videos or
- 00:07:32 some other resource in the internet and
- 00:07:34 here I will have a path and I need a
- 00:07:37 empty path for my route route for the
- 00:07:40 default route and here I wanna load the
- 00:07:43 quotes component and I will add a second
- 00:07:48 route don't forget to add those imports
- 00:07:50 by the way the second route will lead to
- 00:07:53 the new quote path and as the name
- 00:07:58 suggests he rebel load the new quote
- 00:08:00 component also add that import and of
- 00:08:03 course also make sure that if you're not
- 00:08:05 using the CLI you manually add all your
- 00:08:08 quotes to the app module to the
- 00:08:11 declarations array so with that the
- 00:08:14 routes are set up now let's export the
- 00:08:17 router the router module here import
- 00:08:21 that from angler router to for route a
- 00:08:25 Prout's to make them available and go to
- 00:08:28 the app module and add it here in the
- 00:08:30 imports array routing great so make sure
- 00:08:34 to add the import to your app routing
- 00:08:36 file to with that routing is set up and
- 00:08:39 with that we would always be able to see
- 00:08:43 that but right now might change again
- 00:08:45 I'm not sure I also need to set the type
- 00:08:49 for this exported cons there in the
- 00:08:51 routing file and this is of type module
- 00:08:54 with providers which
- 00:08:55 needs to be imported from at angular
- 00:08:57 core I'm not sure if this is intended
- 00:09:00 because normally types could should be
- 00:09:02 able to infer this from well there's
- 00:09:05 Roger module for root method but right
- 00:09:08 now I need to add it to not get an error
- 00:09:10 so after saving this should now
- 00:09:12 recompile I got these server already
- 00:09:15 running and now we see looks good this
- 00:09:19 is the get quotes component of course
- 00:09:21 you don't see any quotes because we're
- 00:09:23 not reaching out to the server yet this
- 00:09:25 is what I want to work on next so to
- 00:09:28 reach out to the server I will create a
- 00:09:31 new service for this I'll name it quote
- 00:09:34 service
- 00:09:35 it'll also place it in the root file
- 00:09:38 root folder excuse me and export this
- 00:09:42 quote service class I'll add D at
- 00:09:46 injectable decorator here to make sure I
- 00:09:50 can also inject services into this
- 00:09:53 service because I need access to the
- 00:09:56 HTTP service to default angular to HTTP
- 00:09:59 service which are there for import from
- 00:10:02 at angular HTTP now I will add a get
- 00:10:06 quotes method here and simply return
- 00:10:09 this HTTP GET and now my URL which is
- 00:10:15 either localhost if you haven't mapped
- 00:10:18 it to a different domain or since I did
- 00:10:20 map it here on my system it's level ng
- 00:10:23 to – view death / API / quotes this is
- 00:10:30 the API endpoint we set up in the last
- 00:10:33 video in this series on our level
- 00:10:35 back-end to get all the quotes I also
- 00:10:39 want to map the response to transform it
- 00:10:43 and for this to work I need to import
- 00:10:45 rxjs /rx to unlock this map operator
- 00:10:49 here I know I get a response of type
- 00:10:52 response responses imported from at
- 00:10:55 angular HTTP and then I can simply
- 00:10:59 transform it so here I want to return
- 00:11:02 response dot JSON and now if we have a
- 00:11:06 look at the
- 00:11:08 response we got back when using our
- 00:11:11 level back-end or our API endpoint with
- 00:11:13 postman let's have a look here you see
- 00:11:16 we get back this javascript object where
- 00:11:19 we then have a quotes property which
- 00:11:21 actually holds the array of quotes and I
- 00:11:23 just see we did delete it so we will
- 00:11:25 have to create one to see it again but
- 00:11:28 the issue or not the issue but the
- 00:11:30 important thing to recognize is we're
- 00:11:32 storing the quotes under a quotes
- 00:11:35 property therefore here when we're
- 00:11:37 extracting this and mapping it
- 00:11:39 I should access dot quotes on the
- 00:11:42 extracted body we're extracting the body
- 00:11:44 with the JSON method but then again
- 00:11:46 quotes to really get that array of
- 00:11:49 quotes and return this and the map
- 00:11:51 method so with that I'm getting all the
- 00:11:54 quotes now it's time to go to the quotes
- 00:11:58 component here where I loop through them
- 00:12:01 and create individual quotes and somehow
- 00:12:04 hook up this get quote or get quotes
- 00:12:08 button so on get quotes was the method
- 00:12:10 name I set up there so let's add this
- 00:12:13 let's also inject our quote service so
- 00:12:18 private quote service of type quote
- 00:12:21 service here also add the import and
- 00:12:25 also of course added to the providers
- 00:12:27 array in the app module quote service to
- 00:12:30 make sure it is available the angle to
- 00:12:33 injector can create it and with this
- 00:12:36 setup back into quotes component with
- 00:12:39 the service injected in on get quotes
- 00:12:42 which is fired when we click that button
- 00:12:44 I want to reach out to my quote service
- 00:12:48 get quotes and this of course is an
- 00:12:50 observable so I'll subscribe to it and
- 00:12:53 here I know I either get my array of
- 00:12:56 quotes this is when we have a successful
- 00:12:58 response and I'm mapping it so here
- 00:13:02 quotes whoops this is just quote of
- 00:13:06 course my blueprint here and then I want
- 00:13:09 to use this array of quotes and we could
- 00:13:11 either also log it to the console or
- 00:13:13 simply set our quotes property up here
- 00:13:18 equal to the quotes we're getting back
- 00:13:21 and we could also of course get a
- 00:13:23 response which is an error type response
- 00:13:26 which our import here from a Tingler
- 00:13:28 HTTP and well here I simply then want to
- 00:13:32 lock this to the console so that we can
- 00:13:35 investigate what's going wrong so
- 00:13:38 omelette code quotes is hooked up in the
- 00:13:40 best case we're fetching the quotes and
- 00:13:42 populating our quotes property we're
- 00:13:45 then looping through all those quotes
- 00:13:47 and replicate the single quote component
- 00:13:51 but there's one important thing missing
- 00:13:53 we're not passing the quote to that
- 00:13:55 single quote component in that quote
- 00:13:59 component we have a quote property but
- 00:14:02 this can't be set from outside so may
- 00:14:04 let's make it settable by adding at
- 00:14:07 input here at input in front of it
- 00:14:10 import input from adding lock or now we
- 00:14:13 can bind it from outside and now in the
- 00:14:16 quotes component here in the template I
- 00:14:18 can bind to quote with square brackets
- 00:14:22 using property binding and I want to
- 00:14:25 bind to quote I'm looping through here
- 00:14:27 so now quote here between the square
- 00:14:30 brackets refers to quote property in the
- 00:14:33 quote component I'm sorry I know there
- 00:14:35 are a lot of quotes and the shouldn't
- 00:14:39 here and D quote here between quotation
- 00:14:42 marks in my quotes components of plural
- 00:14:45 refers to be quote in the loop so if
- 00:14:48 that I'm looping for all the quotes and
- 00:14:50 passed individual quotes a quote to the
- 00:14:53 single quote component here and with all
- 00:14:56 those quotes going on we should be able
- 00:14:59 to now see that in action now since we
- 00:15:02 deleted all quotes in the last video
- 00:15:06 let me quickly create a new one by
- 00:15:07 sending a post request with postman as
- 00:15:10 shown in the last video to D slash quote
- 00:15:14 API endpoint make sure to set the right
- 00:15:17 headers here content type application
- 00:15:20 jason and body raw here let's quickly
- 00:15:25 create a new jason document content will
- 00:15:29 be some quote so let's send it
- 00:15:34 quote was created indeed so let's get it
- 00:15:38 here we see it here now let's see it now
- 00:15:41 running application well we don't even
- 00:15:44 see a running application do we this is
- 00:15:46 an issue kind of related to this issue
- 00:15:49 with the routing where I needed to add
- 00:15:51 module with providers I'm not sure if
- 00:15:53 this will stay or will be fixed if it's
- 00:15:56 a bug or a feature right now in the code
- 00:16:00 service I need to be very explicit about
- 00:16:02 what this get quotes method is returning
- 00:16:05 and this of course is observable
- 00:16:06 wrapping anything so you need to add the
- 00:16:09 import to observable from rxjs and make
- 00:16:12 sure to be explicit about what you're
- 00:16:14 returning here this generally is a good
- 00:16:16 practice but again since we are
- 00:16:18 returning an observable here normally
- 00:16:20 type scripture be able to infer this but
- 00:16:23 I'll add it here with this save we
- 00:16:25 should see that our application now
- 00:16:27 loads correctly and now let's hit get
- 00:16:30 quotes well I don't see any quotes let's
- 00:16:34 open up the console and here we got an
- 00:16:37 error that no access control allow
- 00:16:40 origin is present what is that this is
- 00:16:46 something which is a security feature in
- 00:16:51 general it's called cross-origin
- 00:16:53 resource sharing we're having two
- 00:16:57 different servers talking to each other
- 00:17:00 here our angler queue application here
- 00:17:03 runs on localhost 4200 as you can
- 00:17:06 clearly see and our back-end clearly
- 00:17:10 runs on the lateral ng to view death
- 00:17:12 domain which is a different server this
- 00:17:15 is not the same it's both on localhost
- 00:17:17 but localhost for have 4200 using port
- 00:17:21 4200 actually it's a different domain
- 00:17:23 then localhost whatever port dis uses
- 00:17:27 behind the scenes so both runs locally
- 00:17:29 kind of well this even runs in vagrant
- 00:17:33 here so it's kind of different but even
- 00:17:34 on the same machine a local host with a
- 00:17:36 port is not the same as localhost with
- 00:17:39 no port or some other port so two
- 00:17:42 different domains and this is a typical
- 00:17:44 problem you'll encounter in such
- 00:17:47 application
- 00:17:48 where your front end is served from a
- 00:17:49 different server than your back end
- 00:17:51 normally it's not allowed for both to
- 00:17:54 communicate because it's kind of fishy
- 00:17:55 if some other fronted at some other
- 00:17:59 content wants to access your back-end
- 00:18:01 but we're living in 2017 now and there
- 00:18:06 this is absolutely normal because we
- 00:18:07 have a lot of applications which simply
- 00:18:09 expose some API endpoints for different
- 00:18:12 apps to connect to them and therefore we
- 00:18:14 can fix this and we will fix this in the
- 00:18:17 next video because fixing this setting
- 00:18:20 up the ability for our front-end app to
- 00:18:23 XOR back it up when we have different
- 00:18:25 servers is such a key thing that we
- 00:18:28 definitely need a separate video for
- 00:18:30 this as it's very interesting and
- 00:18:32 something you will need in a lot of
- 00:18:34 different and every use case is to so
- 00:18:36 see you there bye