A Guide to Advanced Angular Patterns (Route Guards, Pipes, Interceptors & more) - JS Marathon

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and not that sighs there we go welcome to a another edition of JavaScript marathon in the angular track today we're gonna be talking about advanced angular thank you everybody for being here if you've been here before any number of times why don't you comments in the chat and let us know how many of these do you been to if there's anybody that's been here for every one of the angular JavaScript marathon sessions definitely call it out I want to say hi to you I want to see some of the regulars saying hi in a little bit but let's get going so my name is Rob Iselle I'm a software architect at this stop lapse you can find me online on Twitter at Robo sell so if you have any questions stemming from this any comments any ideas for future sessions anything like that feel free to reach out to me at robo cell so it's just my name with an extra L and I'm gonna leave that as an Easter Egg for all the people that have been here for every week because I've told the story a few times now how that happened of course we can't do these sessions without our sponsors so our first sponsor today is this dot Labs your partners in modern digital transformation we specialize in mentorship consulting training and staff augmentation for enterprise organizations find out more at this labs comm or send us an email at hi at this dot dot CEO do you find keeping up with the constantly evolving technology to struggle do you want to bring your team up to speed on one of the latest technologies this that loves labs offers personalized training programs to suit your organizational needs ensuring you and your companies stay on the leading edge if you're interested at all by that contact us today at hi at this CEO to set up your complementary needs assessment of course we also have a lot of upcoming events that we want to make you all aware of so the first Thursday of every month we do our angular online meetups so the next one is actually coming up this Thursday so it's actually tomorrow we're gonna be actually having a really special event this month because we're having the state of ng rx we're partnering with the Narwhal team to present state of in grx we're gonna have a lot of the ng our x coordinate team members like Brandon Roberts West Grimes Mike Ryan and Alex of Crisco speaking and just giving various in updates about what's going on with that project and where they're going and based on some of the RFC's and things that I've seen coming out of them recently that meeting is going to be amazing they were going to blow some minds so if you're interested in attending that finding out more tomorrow make sure to sign up at angular calm if you're also interested in react you can join us next Thursday or the second Thursday of every month for our global react Meetup if you're interested in that similar to the angular one you can sign up online at react.js meetup comm I believe the one this month is going to be state of reacts with Brian Vaughn I think is the name but that's gonna also be a really good one our view Meetup we just had a couple weeks ago that where they did the state of huge yes three but the third Thursday of every month we have our global view meetup so if you're interested in that just like the reaction n go sign up at the meetup calm and finally our last sponsor today is infra Geist --ax learn how to build better faster angular apps with ignite UI there are hundreds of ready to use templates angular native components and charts and controls to make your development experience positive ignite UI is the developers choice for angular check out our sample apps and try ignite UI frame killer for free at bitly slash ignite UI free trial and we're really honored again this week to be able to do a giveaway so if you are interested in winning a one-year license to in my UI for angular all you have to do is tweet at this stop media and infra gistic s-- with the hashtag javascript marathon and all you have to say is anything that you enjoy about this session and if you can't think of anything just make something up and we'll pick one of the people that tweets to win a free one-year license so that's really exciting so make sure you do that alright let's get started leave good to see you yeah I've seen I notice you and Lara swell welcome as well man I'm glad that you're joining us live this time and and hope that you enjoy all right so we're time I advanced angular patterns and you know it's kind of interesting advanced angular patterns because there's a lot to angular angular is so deep and in one hour we can't hope to cover anything is so so advanced but you know one of the things that I've been able to notice is that when we teach angular to people or when we work with people that are working on angular projects is that you can build really interesting powerful successful applications that scale to many thousands or even millions of users using only components and services that are using either built-in or third-party tools and libraries right so people are just using what the angular platform gives them and this isn't already incredibly powerful and then there's this ecosystem of awesome companies and awesome individuals doing open source or selling selling libraries that give people the power they need to build really cool things right everything from angular material to ng rx to AG grid and ignite UI and to all the things that we're talking about people build amazing things every day just using what they can get their hands on either in angular itself or or by by open source or third-party library so today we're going to talk about what happens when you want to branch out and kind of start to extend angular platform on your own so we're gonna be talking about things like pipes things like interceptors things like validators things like directives and just to give you everybody a little bit of a taste of what some of these libraries are doing underneath the hood what you can be doing in your projects so that you don't always feel like oh man I don't know how to do that so I feel like I have to go find a third-party library by something hopefully we'll give you some of the tools that you need to really get interested in extending the angular really adding some power and some oomph to your projects now a couple things that we're not really gonna cover in depth today first we're not really gonna cover advanced rxjs ok so there's gonna be some rxjs because rxjs and reactive programming is really key in angular but we're not going to go deep into the advanced rxjs thing so the reason why is because elsewhere in this JavaScript marathon we have a separate rxjs track which is being run and staffed by Ben Lesh the primary maintainer one of the primary maintainer of rxjs so I certainly can't teach it any better than he can so if you are interested in learning more advanced rxjs patterns either watch the VOD of the other rxjs sessions or you know keep your eyes open for other JavaScript marathon sessions regarding them another thing that we're not going to talk about today really is in grx ng R X is an amazing tool I think a lot of people use it to do state management in complex angular applications but the reason that we're not going to cover it today is because we've actually already done two sessions on it so we did I came back and did a session or I was here and did a session on it two weeks ago about directs advanced patterns and then last week we had Frederick do a session on ng rx testing so if you're at all interested in upping your injury or X game those are definitely two sessions that you want to review from a couple weeks ago but we're not gonna go any deeper into that today all right let's get started all right so let me give me a moment while I switched my screen over and if you any of you have any questions you know I'm happy to answer them along the way I may not necessarily know the answer off the top of my head but we can certainly look it up and try to find answers to it so if there's particular things that you are interested in discussing in this session definitely let me know that's definitely truly learning anything from Ben Lesh is certainly a joy okay let me share a screen one more time the screen okay so where are we let me make this a little bigger and on the wrong screen here all right let me make this little bit bigger so what do I have going here what do I have going here it looks like I've done a lot of pre-work and the point is that I have the reason why I have all these files already created is just in the interest of time anybody as you all know that works in angular that if you were scaffolding a bunch of these files and having to make sure that you're adding them to the to the app module and things like that that can take time and that's error-prone what have you especially when you're live coding so what I've done is I have set up some file structures for things that we're going to go through a little bit of some playgrounds so we're going to talk about directives we're going to talk about interceptors when I talk about pipes when I talk about validator and then see how all of that factors in so again if you have questions about anything else or about these you know feel free to ask as we go through just to kind of show you what we have here is just some basic playgrounds so what I'm gonna do is I'm gonna open up the pipes playground and that's actually where we're going to start so what we see here is we have in this pipes playground a input field and that input field this is a number and what we're going to see is when we increase the number nothing's really happening yet but we do see some text a few seconds ago and I think if we go up it's gonna say less than a minute ago and if we make this 60 seconds it's gonna say a minute ago and another 20 it's a few minutes ago okay so here we are let's look into what we're doing here what's happening and how we're gonna try and improve this so let's go into our component here and first of all this is our component that we're working with and this is this so what we're doing here is something that a lot of teams do as a first instinct which is to say I don't have a particular piece of information or a piece of my data isn't structured the way I want to display it and it's not necessarily trivial to know how to do it in my template so what a lot of teams will do is they will bind to a function call and well this isn't necessarily always an anti-pattern there might be circumstances where it's very difficult to get around this or very cumbersome to get around this what you have to realize when you do this is that you are creating a situation where angular can't help you out performance wise by doing a lot of really cool caching or a lot of other cool optimizations that minimizes the amount of times that you have to call this method so if we look at what this convert time method is doing it's taking a number of seconds and it's trying to do something that if you've ever used like a moment library or something like that it's trying to convert some number of seconds into some sort of time stream right and so it's doing some comparisons and saying if it's less than this if it's this and this or whatever change the value to whatever and this again is fine it will work but we have to realize that what's basically happening is kind of like as this component is is is mounted it's just sort of like periodically calling this function right it's kind of saying hey you know is this function still the same as this function still the same is this function still the same give it the same inputs but I don't know that it's necessarily Peter out so you know it's just calling it's calling is calling and so this is going to be something that can be problematic for us so what do we want to do well first of all what we can realize is that perhaps it's the case that this general conversion strategy is not necessarily something that we want that it's not unique to this component it's just something that we first used here so it might be generic it might be reusable but it's also gonna be something that we might want to just make into a simple transform so what we're going to do is we are going to make a pipe for this and so I have it set up already it's over here so it's the relative time pipe and when we're creating a pipe we basically give it the decorator of at pipe so just like um at component or at injectable or after active we have an at pipe and we'll give it a name relative time in this case and then that will create a class relative time pipe that's going to implement pipe transform and pipe transform is basically a interface that just sort of made sus put in this transform method now in this transform method we can kind of take whatever we want to take you know as the the value this is basically the value that's coming into the pipe it's what's being passed into the pipe and then return whatever we want okay so in this case we need to take the number of seconds which is the value we know is going to go into it and then we're going to return a string so basically we just want it to be this method and so we're going to take this and we are going to return back so what we're doing here is if the seconds is less than 15 we'll say yeah that was a few seconds ago right if it's less than a minute we'll say yeah less than a minute if it's less than two minutes we'll say it was a minute ago otherwise if it's less than four minutes we'll say it's a few minutes otherwise we'll give up a precise number of minutes or we'll say it's an hour ago and Oh more than an hour ago right could we come up with more ways to separate this all out yeah sure we could but this is what we'll go with okay and so this is as simple as it is right we know we have seconds as input and then we just return the string output that we want so if we save that and then we go back to our pipe our pipe test component and what we want to do here now is instead of calling this method first let's just make sure that we have cleared out the other thing okay so just prove that I've actually set this up to work correctly so now we're not getting any translation but now let us use this pipe that we used so we called it relative time and if I say that I notice how it sounds a few seconds ago right and as this value is changing being updated because it's a new input to the pipe but otherwise it's staying constant what it was before and now we're at 15 now we get less than a minute ago right succeeds a minute ago we'd like to go up to 240 to get to 4 minutes ago and so on so a very straightforward simple pipe and I think maybe many people have used pipes like this but you'd be surprised how often you have missed opportunities to do this I you know this happens with address concatenation with name concatenation right you can make a name type that takes some JSON object that you have representing a name combines the first name last name the honorifics whatever else have you that you have I think I see a lot of people do that formatting either in additional rxjs operators that they put on their data like extra mapping operators or they do it and functions and things like that and you know sometimes those those places are called for but you know if you're gonna reuse a transform over and over again rather than you know copy and paste that code into multiple rxjs operators or even make a custom operator for that much better to use a pipe for circumstances like this now the other thing that I'll call - because I had done this leading up to it is that if you are going to use these pipes you are going to want to make sure that you are including them in the module and they go into your list of deck patience and that's gonna be able to give you access to those pipes because otherwise your components aren't going to know that they exist so you can't just like it will just look anywhere for it you have to declare it in a module that your component has access to in a you know in whatever way that that is and then and then you're able to access these in your template okay so that's it for a pretty straightforward pipe but there are other things that we can do than just a simple input and a simple output right you can have these parameterised pipes you've seen these elsewhere there are built-in pipes that are parameterised for things like pattern matching for things like conversions format conversions and things like that and so we will show how to do that so what we have here we were converting this into it a string but you know one of the things which is really funny there are a lot of libraries out there that do plurals for people this is not going to be the optimal way to do plurals okay but I just wanted to show an example of being able to pass in multiple parameters to something so what if we wanted to say based on this number of seconds or this number of anything for that matter what is it like let's give it a label and let's be mindful of those plurals now you can do the ng plural you can do different libraries that do this again but we'll just show how to do it with a pipe parameterize pipe okay so what do we want to do here let's open up our PluralEyes pipe so already well already but you can see that this is a little bit different of a interface right so it's still a plural I so still a pipe and we're calling this class PluralEyes pipe we still at pipe we still have a name so this is the the name that will actually go after the bar after the pipe in the actual template and it still implements pipe transform here we still have the value now again we can name this whatever we want here we're naming it value because it's still reading from that value of seconds elsewhere you know if you don't know what it's gonna be in the end you can string it and just like cursive do that you're going to do but then we're going to take two arguments to this so you can have your pipes take as many arguments as you want to and the way that that manifests is you'll have like some binding which is something like value and in this case flips there we go Lorelei's pipe and then you'll do these the quotes we have a colon to separate out the arguments so this would be like our twine R 2 R 3 etc so that's what we're going to set up and right now it's returning nothing so what do we want to do here well what we want to do [Music] basically just know that we want to have some sort of value and then we want to give it a label right and we know that that label is it's the value equals 1 then we're going to use the singular label otherwise we're going to use the pole and that's it now these arguments don't have to be this way again we could do whatever we want the sky is really the limit here with the proviso that it needs to be synchronous but now when you come back we see zero seconds one second two seconds right and did I actually have that already working I didn't delete that oh yeah so here we go so here it is PluralEyes and we pass in the first argument which is second that this gonna be the singular label and the plural second label is seconds so you can do this to pluralize things you can do this to convert numbers to strings or strings to numbers you can do this to do JSON transforms we'll see later other pipes if you haven't used them like the JSON pipe or in talk about the async pipe in a little bit pipes are magical and often underused you know because the built-in ones are pretty good most people just only use those they just don't realize how simple they are to create they're really one method and you'd be amazed at how much performance - musicians you can get especially on a really large page I mean if you're doing these method bindings in your code and and you have a lot of ng fours a lot of repeated data on your page a big table you know you're really gonna suffer performance wise there okay so that is our our pipe test so we started off a little slow a little a little a little intermediate level and we're gonna get a little crazier now any any questions about pipes okay you guys will be hearing me in the future so if your questions will circle back around the next one we want to talk about is we want to talk about the validators because again validators are something that people use a lot of built-in wise but don't necessarily realize that they can do validators themselves so what do we have already going that's like a alligators so what we have here is a pretty straightforward form right we have this password field and we have a confirm password field so what we have here is basically oh yeah so taking a break up watch the ask how many arcs can you pass to the pipe so my default answer would be what Daniel says that you can pass as many as you want you may or may not have to be careful with typescript so there are some things that will accept arbitrarily many arguments but you may lose typescript support after a while but because you control the types on these pipes I believe the answers correct that you can do as many as you want so we're basically doing like a sign-up form here we have a password field we have another confirmed password field and we have a bunch of pairs right so this is stuff that maybe a lot of you have done with forms but one of the things that some people don't necessarily know of course is how about some of this up how to do some really interesting validators that may or may not be built-in by default so looking at what we have we have a bunch of syntax here we're not bound to anything yet or to talk about that in a second and we have the only thing that I think I'm coming here with is I have a validation service this is so that we can do async validation and it's just mimicking a back end here and after five seconds it's going to do a check so it's gonna mimic like a delayed asynchronous validation and we'll go into a little bit about what that is so let's start building this out in our components so let's open up our component in our TS file so first of all what we need to do is we need to create the form that we're going to actually be working with and so let's do that now okay so the first thing that we want to do is we want to bring in the form builder we're using the form builder here rather than the other method of managing forms because I just like this way of building forms the reactive forms I really think that this is ugly the most sturdiest way to be operating with forms certainly got one of the best interfaces I've use is working with forms so I would definitely recommend it so we're going to be setting that up now and so what we wanted to do now is in our knit function we're gonna actually build out that form right so we're going to say oh here we want to put it in aqua so we're gonna have a login form or a sign-up form is a fun group and here we're going to have this stop login form equals this thought form build or a paste we're gonna in stand or we're gonna activate that form builder and we're gonna make it make us a group and in that group we're going to start adding in some controls so the first control we're gonna have is the password control and it's just gonna have the only one validator that we're gonna have is that it's going to be required right so this is one of the built-in validators we haven't done anything custom we're gonna say that this is a required field and we're going to say that we have a confirmed password field and this is also going to be wired and that's where we're going to stop there for now also know that when this actually logs in or submits the form it's just gonna set us submitted to truth we're not actually going to hit it back in for this just first simplicity's sake okay now one other thing that's really good to do with these form builders which we can do here is that we can also expose some of the actual controls in a slightly easier way so of course you can go into your template and you can do you know login form get and do that everywhere or you can expose your individual fields with accessors like this so you do I get password and then we can say return and response for login form dot get password and then similarly we can do that for confirmed password and it's just going to give us a little bit of syntactic sugar to get access to the fields the way that we want to have them inside of our template okay so we so far we have this very basic form here now we have to actually like hook it up so how do we hook it up when we go in here of course and we will set up our form boot on our form so we're going to do login form and then we know we have a submit or you know we have a in G submit it's gonna be login okay when we have that and so we know we have this password field so what do we need to do here here we need to do form control maybe to bind it to the correct part of the form builder that we did so here we're just kidding if anybody's unfamiliar the phone form builder is basically giving us like this sort of really well-documented really well developed sort of OSA set utility for accessing for managing these forms for getting whether they're valid or dirty or or when their value changes you get all these really really really cool utilities in reactive form group that we created and then what we're doing is connecting the pieces of that to the individual UI elements that will drive that part of it and it just does so much work for you that you would otherwise have to do for yourself it's just so so nice to do that so that's all we're doing here if anybody's unfamiliar if you're just connecting the pieces that we've already built to the pieces in our UI okay so now we have this we come down here and this is another form control password Oh Mac it's hopefully that's still built okay it's still built and then if I do this now I should see the whole form disappear and the form disappearing means that it actually is submitting appropriately which is good okay so the other thing that we can do now is we can start making some things feel a little bit more interesting so the first thing that we're going to do is only show the errors when there are actually errors to show so let's do that now so we want to kind of hide this in a certain scenario and let's think about when that might be so what we want to do here is we don't want like errors to show up the second that somebody starts editing things so we might want them to or the second that somebody opens up the page drive you know what the page to open with errors so we might say that we want to wait until people have actually maybe interacted with the form so we could do something like password dot 30 so checking to see whether the field has actually been edited since it was last validated or since it was last submitted and also we can be password touched to make sure that it's actually been accessed or touched excuse me to mean that's been accessed so either it's been changed or it's just been accessed and we'll go password imbalance here so what we want to do is we want to show these errors if it's invalid in some way we don't need that we know why it's invalid but we know it might be invalid in some way okay and so now if we open this back up we should see now that all the error messages related to password are gone and and just do style it's blank I heard of that guy for a second so he's out of the way okay so go back to this so now if I come in here and remember it's required so if I leave if I leave validators required if I leave that pass for dirty old password touched and pastor Don balón I do hmm that's for docking valid other than this up I know this works did I get ahead of myself walking for anybody sees it let me know but I'm just gonna keep going then hopefully these will start appearing here soon so what we have is we know some of these errors when they might appear so what we want to do is we want to say that this is in G if if in particular so know that though this whole div will show if there's errors but we want this individual error to show when particular errors appear so when particular errors appear we can get to them by a bit errors object which doesn't always exist but it can exist and the errors get special labels is it from the get password yeah it should be getting it from password which should be getting it from login form password should be getting it from here most I'm less I'm missing a typo here so I don't think I am anyway I guess I will keep going if I need so I got some notes I can copy stuff over if I somehow typed out something I just for some reason I'm blind it always seems so obvious when you're watching somebody code from this side it's like completely not obvious okay so we know that we want this airs this errors property and it doesn't always exist so here we'll have requires so that's going to be the name of this hair and generally speaking the validators name is also the name of the air that shows up so here we have required now we know we have these other errors three of everything or actually two of them we think and password is this password is not allowed and we don't know what causes those to happen yet by the way one in the keys class class error was up there okay so we know we want these so for now we're just gonna hide these password okay so now we're actually causing errors for ourselves what have I done fine this is all correct not submitted correct label correct all these correct Oh when in doubt always open up your console what's it complaining about no value access ER for forming form control with name password know what value access or accessing trying to do their setup form add control engine changes [Music] does anybody see it what am I missing here logins form equals this stuff or builder doctor object that's the key oh did I put it on the label instead oh thank you so much oh my goodness look at that thank you I put it right below and I did it wrong here Thank You Vladimir for saving the stream you are a hero of the screen okay let us put this back okay like I said it's so obvious for you all on this side it's it's less obvious than you think okay that's word got dirty or password touch and password invalid and now we go back in here and now we actually have to go into the password and once we leave it or change it now we see the password apart okay that was just meant to be the easy part okay so now we get to the market some more interesting stuff same thing down here it has the same issues so we are going to know interesting that I made these different oh that's good it is a different class of error okay so for now we'll leave that but this please confirm the password okay so what we need here is the same string basically so here are the errors for the other control which we have to change this to confirm password and that should make those errors disappear so this is a shared side there so we'll make these disappear entirely for now we keep doing this display:none just to declutter the screen okay all right so now we are here so now the other thing of course that we want to do is we want to make our button disabled the form is invalid so this is again another awesome part of of the form groups is that you can do login form got invalid and so in this way now we're not going to be able to submit until our thing is Fallon so we have this and we have this we're gonna get this since we have to do that I'm gonna do that and now they are alright alright so that is it okay so let's let's actually get to the part that was interesting or supposed to be interesting let's talk about some custom validators so let's talk about validators to do with individual forms first because these are interesting so again there's a lot of built in validators we use one of them the validator dot requires so what do we actually have to do when we actually make our own validator it's relatively straightforward a validator is actually just a function that accepts a control and then returns some set of validation errors which is really just an object with with strings keys and boolean values on the other side so what do we want to do here we want to check for a pattern validator and so what I'm going to do is I'm gonna put a little bit of code so what we want to say here is that people have to put in we're gonna put some requirements on the strength of our passwords so we're going to say in order for a password to be valid it has to have two capital letters two lowercase letters two of these arbitrary symbols and two numbers zero to nine right so this is terrible and all websites that do this end up being terrible but we're gonna show this as an example of how we can do validation so what we're saying is that in order to be valid the control that value which is the control which is passed in so the control to which we put this validator it's value needs to have to capital to lowercase two symbols two numbers and if it's not true for any of those valid is going to be false so what we want to do here then is say if valid then we want to return null so when you when you something is valid you want to return nothing that's the indication that there's no errors but if it is invalid in the invalid case we want to display an error and to do that we need to give it a name so again usually the validators are named the the validator error string is usually named the same thing as the validator doesn't have to be though but usually is just for simplicity and clarity sake so the password pattern validator will have a password pattern error and that will set it to true so validators are actually really straightforward to make you can make them in line in your methods you can put them in utility files you can stack them on top of each other you can do whatever you want they're not actually classes they don't need decorators they're just functions you can actually do them as arrow functions as well and define them actually in the forum group builder which is interesting I don't ever see anybody do that but just to let you know you could alright so now to do this we need to add this validator to our passwords object and so we have the validator required and then what we want to do is add in our password pattern validator that's all we have to do so this pattern pattern validator is included up here I actually now forget off the spot my head I always forget what things need to be included in here it doesn't actually have to be included yes right it doesn't have to be included in here because it's not being injected so we don't have to worry about it in that module or in injected anything like that you can just go directly into our component and now we have this second error that must have two of everything and we can actually change this now to be ng-if password errors but password so now if we go in here if we come in here we should see password is required password pattern didn't work go check it wasn't called password pattern was it okay good now I should see both errors okay two of everything all right so if I type I can get rid of the required one but I actually need to follow the route so I can do like a a SS OOP I gotta be careful here TD any numbers one two I need some symbols there okay and so now I am meeting this arbitrary password validation right so you don't have to rely on the server necessarily do it you don't have to do it at the point of submit you can just build it as this custom validator super straight board okay now the next thing that we wanted to do is we want to make sure that the two passwords match now how can you do this one of the ways that you can do this of course again is token to submit or to do some weird things like that but one of the ways that you can do it is actually to create a validator that works on a form group and not just on a form control so that's gonna be the next piece that we want to do so what if we want to do a matching validator that is actually um something which is going to return a form take a form group and return validation errors instead so again this is just a function so it's very much like the control validator except for now you have a form group instead of a form control and so you just have to be a little bit mindful of that so in this case what we're going to do to make this work is the first thing that we have to do is get the actual controls that we are trying to match so let's a password field and we want to do group because that's our form group when you can get password uh now you know you can't be defensive and make sure that that thing actually exists you know you're gonna if you're not harden this for production you know you might want to be careful but I'm just gonna move forward blindly and hope that I get it right because you know that's work so well today and we're gonna confirm password and we're gonna be value here so now we have the password value in the confirmation value and what we're going to return is either there's no password if there's no password or no confirmation we're just gonna say that um we're good there because we know that those fields are required so if they haven't entered them yet it's it's going to be invalid in another way so let's not double mark things is invalid so let's say that if both of both those fields don't exist or the password matches the confirmation so these are all valid scenarios if you haven't filled out one of the fields or if the two fields match that's going to be valid otherwise we're going to show matching passwords truth indicating that there is a matching matching password era right so again it's valid if not either of them don't exist it's only valid because you have a required validator already on them but if the passwords match if any of those things is true we're gonna have no error otherwise we're gonna show on matching passwords error so how does that work out let's go add that in so to do that now we can't put it on any one of these one controls we actually have a second argument now here for the form group itself where we can pass in validators and in that validators we can BDD password actually passwords validator packets including it in the file at the top or whatever and now that moves in so that will control validity now but it's not going to show any errors so let's do that so let's come in here that's what this down here the passwords need to match so we can get rid of is display:none now switch that with a ninja if login form pairs let's go back in here and let's make sure that we have a and now let's go B and now the passwords don't match by the goo-gaa now the passwords match voila this is something that a lot of people don't take advantage of again form group validation it's incredibly powerful concept to combine it to to validate groups of fields together you can do you know any business logic that you want to you can do it synchronously or asynchronously it's incredibly powerful I think a lot of teams spend themselves into knots not realizing that they can do that ok next thing is what if we wanted to check now this is a good security practice but what if we wanted to check to make sure that the user wasn't using a password that we didn't want them to have like what if we were keeping a list of passwords that are known to be compromised in some way and we wanted to make sure that the user wasn't picking one of those the only way that we might be able to do that is to access it via the server so we need to actually get access to a server to do the validation and so one of the things that we can do here is to create an async async' validator and so that's what we have here is this forbidden password validator now the reason that this is a class and not a function as it has been elsewhere is because we actually are we need the injector here so we're using the injector to get a validation service now this service again remember it's mocking HTTP its mocking as if it was a server but you know we're gonna pretend like it's actually hitting a server and asking whether a password is fine so this class so that it can get access to the injector is it's a class and then it exposes this validate method and now this validate method should look familiar to you it's taking a control and it's returning back now not a set of validation errors but a promise or observable to get validation errors right because it's asynchronous so by default here we have it set to none but let's look at what this might look like so we know we need to use that validation service so we're gonna do the validation service and it has a validate password method and we're going to pass in the password so we know we have this control and so we're gonna take that control but value which is the current value of that control and we're going to pipe that so we use an arts Jess here pipe that and math and what happens is we're gonna get back a boolean from that service now again you might get different data back from this service but for our services gonna return a boolean if it's forbidden password and so if it's forbidden we know we want to return forbidden password true otherwise we're gonna return null and if we happen to hit an error with the server we're just gonna give people the benefit of the thought the benefit of the doubt that they don't have an error so we're not going to make them pay for server errors but you could make this an error though if you wanted to you know you could make this server error whatever you can make it whatever you want it to be but we're not going to hold people accountable for server errors so we're going to return null if you get an error from that service which we won't get an air from that service because I'm not demanding that locally but this is the basics of how you would implement and you know any asynchronous validator it's very similar to the synchronous validator except we're just dealing with observables or promises and not simple values if we go back to our component now this is where things get a little bit more tricky within reason though so we don't actually put the validators together the async validators together with the the other validators they're recorded differently so that angular can track them differently so what we need to do what we're going to do because we also want to change a little bit of behavior if you want to change this second configuration object to actually be an object instead of an array so when was it array it was just assuming it was validators but because what's going to be more complex than that we're a switched over to an object this object is gonna have a validators property and this is where we can get our valuators back right so we can get validators required and then validate what does it need to be it's a pattern ask for the pattern validator and then we know we want some async validators and here things get a little interesting so we need to get access to that async validator service thing that we are working on so here we need to actually bring it in and we can call it you know what I call it I call it forbidden validator validator this validator and so here we have this Save open it down and we need to get access to it here so we're going to do the validate functions or that's the actual validator function on this that does that listens to be discarded they stop that okay and this is great but we need to actually do one other thing which is really tricky to people to understand is that because I needed to use the injector I needed to make a class because I needed to make a class but I only want the validator to be the function I've actually lost the reference to this inside of validate so you have to accomplish this is one of two ways so one way you can do this is by creating an arrow function out of this you can do that or you can do find this dot forbidden validator service so you basically take that speck method and you bind its value of this to the actual service again and this will give it access to the service that it actually needs if you don't do that it's like I trying to make a call out to an injected service but I don't actually know what this is it doesn't exist so async validators because they often need the injector and implemented this way they end up having this interesting circumstance with fines so it's just something to be aware of the last thing with async valide is that we're going to talk about is that because they are asynchronous you may not want them to happen on every single key press in the input field because you might spam your server so we can change our how often our validators fire by changing the update on proper to be something else so for example we can set it to blur now all our validators don't occur while we type they occur as soon as we blur the field and now all of our async validators are going to be working so let's set that up here eg if a password there's not for the password it's good there now one other thing is remember we had this validating password just to show everybody what that looks like we can do in G if you can actually get access to that you can do password dot and and password password penny yeah this field pending means it has an asynchronous validator that's still operating I know we can come down here and we can say well I don't want anybody to submit if if they're still running the validator so I want to do login form doc pen means if there are any asynchronous validators operating I also want the submit button to be disabled okay so here we are with our field against now again if I come in here and I don't type anything I get my hairs and so if I delete that okay and I need to confirm these two passwords okay so now what's gonna happen the asynchronous validator isn't happening yet because it gives the synchronous validators a chance to operate first so we're gonna actually force it to make a call to the server by making all the synchronous validators correct now the asynchronous validator fires and I see no wait I see no air why do I see no air forbidden validator forbidden service it's not allowing me to do a a 1:1 capital is that not what I have a 1:1 capital okay so let me see if I type out forbidden password if it's forbidden forbidden passive again yeah to me here password it affects both so watch T it actually affects both sets of validators if it hasn't forbidden bastard password is not allowed this password should not have been allowed Wow okay isn't a lot just taking a second to work okay so that password is not allowed but if I change this to something else then it will but notice I can't submit now until that complete so if I were to make these things match once it comes back from this asynchronous validation here it's doing that now if I switch it back to this cleared this one because the passwords match now it's doing the validation as soon as the validation comes back I can submit and we can move on okay so that's validators again asynchronous validators they can be tricky to use and use them sparingly because they can slow down their users quite substantially but please use synchronous validators and especially form group synchronous validators there is one other thing i just really quickly want to show you which is that you can parameterize your validators as well so over here in our pattern matching service remember we looked for two patterns you can actually do you can actually parameterize this and down here you can actually have validators synchronous or asynchronous that return a validator function so this becomes a constructor function which returns a validator and in this case what we did is we allowed it to say well maybe we want a validator that doesn't just enforce two of everything but rather any number of things but that it's up to the discretion of the writer of the component and you can have that here where you can now switch the validator that we built pass it three instead of two and now it's gonna make me remember this was a valid password before it still says two of everything that's just because we would have to hook that up but now if I go back in and I add three of everything now it'll work Yeah right let's cover a one more topic and let's talk about pain receptors okay so interceptors are really cool because they and effectors are really cool because what they allow you to do is to make changes to HTML or HTTP requests externally without necessarily having to do them in every single service that you want to have to interact with so let's open up the interceptors piece so that y'all can see what we're dealing with so interceptors what we have here is we can set a user so like I can type Bob and I can set that user Bob and then I can get a number and that number is gonna go out to the random.org website is gonna get a number so I've got three now got two it's a number from one to six so it's like rolling a dice I'm rolling a die so here's what that looks like so we have two buttons one that changes the user one that gets a random lumber we have a simple input bound within G model we're not using form builder here just for simplicity sake and then we're just showing some data what does that look like in our template it looks like this so far so when you get a random number it makes a call to random.org you don't have to worry about that too much and then it's gonna console.log the number and it's also going to put the number onto the screen okay so we're making this call to http and now we're going to look at some different ways that we can influence this okay so the first way that we're going to try and influence is excuse me is by proxy the result so what does that mean what that means is instead of contacting HTTP random.org what if I just wanted to pretend as if this was like a local API and I have slash proxy slash integers and then the rest of it and I want that to actually make sure that it goes to random.org so just to show that this breaks if we look down here go to the network tab and close this tab what's gonna happen when I call yet number is it's going to fail and it's gonna fail because it's trying to call an API that doesn't exist right so let's fix that so let's go to this proxy interceptor so an interceptor is implement HTTP interceptor it is an injectable element so it could be injected into route automatically for you otherwise you have to include it into your app module what you have to do actually have to do that anyways and I'll explain what we have to do to get that to turn on but the interceptors take an intercept method and it gets two things so it gets the request so the request that the outgoing request that was made and then it gets next which is a handler and so and it returns an observable of HTTP event okay so by default and interceptors that does nothing simply let's the expression the request go through and so to do that you do next dot handle request okay so next is that handler you say handle the request I was given but now we can decide to do more complicated things here if we want to so let's say that if the request URL so the request has a bunch of different fields on it but if the request URL includes proxy okay so if we if somebody's trying to get to it URL that includes proxy we want to actually do something a little bit special so what are we going to do well here we are going to return next stop handle so we know we need to be next to handle no matter what but we need to now determine what it is that we need to do well the thing that we do is we actually do request clone so we're going to make a clone of the request but we're going to change something about it so what are we going to change about it well we're gonna change about it is its URL right so the new URL for the request is going to be request URL replace and we're going to replace the proxy part with HTTP WWE and gorg okay so you know you could imagine you could use something like this that if you wanted to just go to slash API and then depending on which environment you're in you could go to different servers for your staging server your production server your development server this is one way that you can do something like that there are other ways that angular provides to do something like this but I just want to show you an example of what you can do so one of the things that you can do is basically proxy requests all right so now we want to turn this on to turn this on we actually go back to the app module and when you go to your declarations or some your providers you have to put in these sections for a providing HTTP interceptor so you provide HTTP set interceptors use class the interceptor you created okay if you only have one I think you don't have to put multi true but we're gonna be more than one at a time so we're do multi true to indicate or have multiple of these but we can have this interceptor so now if I save this I should have activated this proxy interceptor and now remember this wasn't working it should now work again azam it works so my actual request in my component is to slash proxies whatever but what if this interceptor did has got to hold that request and before it went out to the wire switch the URL and then sent it back on its way and everything else just behaves as if nothing happened okay let's try another interesting one let's try caching so with caching you know this is a very rudimentary caching situation of course well let's just say that we want to make another interceptor and in order to have a cache when you can actually have a cache let's just have an object and so one of the things that we know we want to do you know we can do something fancy like if the method of the request is not equal to get you know we don't want to like you don't want to cache post request that seems weird only if somebody trying to get data who want to simplify that but so it's not a get request again just handle will just pass it through like nothing happened or we can go and try to see strategy for catching errors great question we may get a chance to get back to it the monk has Const cache hit equals miss not cache requests that you actually will get back to in a second so if you hold on one moment we get good so if we're looking for something in the cache we're going to look for it here so if we have a cache hit what we're going to do is actually return of cache hit and you're like okay well what is catch it what is it what is its type we'll get to that in just a second here but if we've got something out of the cache we're just going to return an observable that returns that thing okay but if it's if there's nothing in the cache then what we need to do is pass it through but we need to now add a little bit extra so we need to actually listen to the result the response and so the first thing that we're going to do is do a tap operator because we don't want actually change the shape of the return value but we do want to respond to it so what this gets back as an event an HTTP response or a it's an HTTP event excuse me and we're gonna do an operation here so what we're gonna do is if event instance of you should be response so if the response was successful the event is going to be an instance of HTTP response if it was an error it won't well it'll be different but we'll do is this stock cache request URL so for that URL we're gonna say that the response was the event so we got an HTTP response when we made a request to it to a certain URL and so if that if that succeeds we're going to store that in our cache okay and then that's basically it so that's all we need to do there so you know you're asking how you would handle errors this is one of the ways that you can get for catching errors with the Interceptor is that after you've sent out the request if you get back something from the request and it's not the correct response you know that it an error message and you can get into this and start looking at status codes and you can actually do interceptors specifically that are geared more towards responses then towards requests and you can do things like show modal's or or toasts or log errors or whatever you want to do so you can hook up logging in this way for errors for your API this is no longer readable okay so that is that now let's turn this caching interceptor on and let's see what happens so now what's gonna happen is you're gonna see down here that we're gonna make a call out to the database right now when I hit this button again I should see another request go up well I shouldn't but I would expect it to so I hit the button again it doesn't and if I look at my console remember we were logging these every time I hit this I'm getting a new value it's actually processing correctly but they're requests the Interceptor is caching that I'm trying to do the exact same request again it's caching the result and it's giving me the results now when I'm looking for random numbers do I want to cache random numbers no but so you can actually you know again just like we did with the proxy you can only turn cat you can turn caching on only for certain endpoints or when certain things are true about the headers you can you can make this customize this in a million different ways this is just meant to show you that you can actually prevent a request from going out to the network at all with a cache using this interceptor and that's not integrated into your services that's integrated entirely through these interceptors sort of put on top of everything so I'm gonna turn off the caching one because that's actually gonna cause any problems right I actually want to make calls up to the server let's talk about one last one okay so this one is well let's not let's not turn it on quite yet the headers interceptor is one that's the most common and so I include it just so that everybody can see what it is that we are you know what would it wear will you use this the most often and the place that this is used most often is to put like headers into your authorization headers into your requests so a lot of times that you know you do that in all your services like constantly I go put the authorization header put the authorization header put the authorization header here you can actually do one intersector and you can grab the users like token or whatever it is that you're using for authentication and put the append that to all of the requests that you need to through an interceptor rather than copying that to all your services so the way what we're going to show how this can be done or is often done is we have a user service okay and on this user service is just returns back the login users remember and the UI we gave people away so in this UI we gave people a way to set the user this is going to be relevant and so what we want to do is we now want to use that user so what's interesting here is we're not gonna start with next because we actually need to get the user so let's get the user first so let's do user service dot user data dot type and here we're going to do a switch map right so every time when I get the user because itself an observable I want to now convert that I'm going to use that user to create a different observable but I actually want to return which is going to be this HTTP request so I'm gonna get the user here and my switch from from wristing emitting and what I'm gonna do now is I'm gonna do next I handle write again exactly what we usually do and we're gonna do request clone right because we want it to change something about the request what is it that we want to change well catch ange we actually want to set some new headers what headers do we want to change what this property actually takes an object of the headers we want to set so here what we could do is just you know just for the purposes of showing y'all like that you could put anything in here you want it's gonna fail the request but I'll show you what it does here we can set headers fake header using users okay so let's go turn that on so let's turn the headache Lewton off the caching lunch the heading headers one okay and so now let's put Bob in and you see we had saved user Bob now let's get this let's try to get a number now what's gonna fail is that chrome is trying to stop me from from using headers to exfiltrate information so it's doing its job ordinarily you wouldn't do this with non-standard headers but I just want to show you that it actually put it in there so you see it's got a fake header of Bob I can make that a little bit bigger of qualities if that's not super readable but you can see it added the fake header of Bob to my actual request so it's actually did work now you can do this again usually with the authorization field is what most people do it with you can do with any header you want as long as the headers valid or that your your server accepts it and you can do that so let me give you the one last thing and this is honestly the reason why I went to interceptors is because this one is tricky does anybody know what is wrong with this code here's what's wrong with this hope for a moment here I'm going to just pretend like I didn't clone the request okay again ordinarily if I was going through the trouble of getting the user I would put it in my authorization field this API does not take a bear token or anything like that so I can't pass it that so let's just pretend that that's what we actually did here was we manipulated that request to accept that that new header let's not do that what is wrong with this code it doesn't look like much is wrong with it but there actually is something wrong with it to show you what's wrong with it I'm gonna go here so okay so we made this change we'll save that this will load okay so we're gonna do is we're gonna set the user to Bob okay and I'm gonna clear this tab and what I'm gonna do is I'm gonna get a number okay number was one I'm gonna get a number number is six I'm gonna get one more number numbers one okay so now I've gotten three numbers now I'm gonna change the login user to Suzy watch the network tab boom what is that three requests went over the line this is a really common problem when using interceptors that pull data from another observable like a behavior subject service or an NG rx selector or what have you and the reason why this happens is because in my component I'm not unsubscribing from this HTTP request now a lot of times people might put this into an async pipe that'll do the right thing but here I'm just subscribing to this observable and then I'm pulling the data out of it why is this a problem it's a problem because usually my HTTP requests end after one call right they just terminate that the the the thing closes but what now has become my new request it's not the function call to http that I'm used to it's the return value of the Interceptor not the head yeah it's the return value of the Interceptor what is the return value of the Interceptor it's not the result of this switch map I mean that's what comes out at the end but it's not that it's it's piping into this user surface so it's actually this observable which never dies that's happening so if you want to get around this you can do something like I take one or you can cause your components to unsubscribe but whatever you need to do but be mindful of that that the thing that you will actually subscribe to in the end is the return value of this Interceptor not necessarily the original request so if we do it take one here now when I open this up and I say Bob said user and I get a number and I get a number I get a number now I switch it to Suzy okay so that was the one thing that I wanted to make sure that I got to was the interceptors because I've actually seen this now on a couple different client projects and in different people's conference talks it burned us on one project one time be very mindful of this always be careful with rxjs when your observables get some unsubscribe but particularly with interceptors ok I take an extra bit of your time today everybody thank you so much for coming out this session of JavaScript marathon again you know if you've been to a JavaScript marathon if you if you've been to these sessions we thank you there are more sessions today we'll be doing this again in future months too so we really hope that you come back for these if you have any other questions a force I didn't get to all the content today so if they've any other questions about any other cool things that you've played around with angular area that you're interested in learning more about please let us know and of course if you like trainings like this or you want to see more trains like this either at your company or otherwise feel free to reach out to us at hi at this dot dot co to set up your complimentary needs assessment so thank you everybody for joining I hope you enjoyed and we'll see you next time thank you
Info
Channel: This Dot Media
Views: 18,406
Rating: 4.9040766 out of 5
Keywords: JavaScript, Angular, Vue, React, RxJS, React Native, Flutter, Lighthouse, Cypress, Bazel, NgRx, Node, Ember, HTML, CSS, Tailwind, TailwindCSS, web developer, javascript tutorial, programming, architect, This Dot Media, Tracy Lee, Google, AWS, Azure, Microsoft, software engineer, developer, Laravel, NextJS, nuxtjs, women in tech, 100 Days Of Code, VueX, react hooks, GraphQL, react js essentials, angular essentials, vue js essentials, API, modern web, podcast
Id: wWEJnolhb_s
Channel Id: undefined
Length: 75min 25sec (4525 seconds)
Published: Wed May 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.