Login UI using BLoC with Flutter | Day 21 - #30DaysOfFlutter

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everybody it's your boy kilo loco and today we're going to be working with flutter so we're coming in at day 21 of 30 days of flutter and in this tutorial we're going to be working with a login ui so we're going to be building out a login screen and we're going to be doing everything using the block pattern so this is a extremely different approach to building out a login ui and dealing with state management and it's a little bit complex but i'm going to walk you through it step by step oh yes with all that said let's go ahead and jump right on in so as you can see we're starting off with a very basic app nothing too crazy going on right here you know we just got um you know our stateless my app widget right and then we have the login view so nothing special going on at this moment so the very first thing that i want to do in this login view is build out a password field which is actually going to be of type text form field or form text field or something like that but let's go ahead and add that in right now all right there we go so we have this password field which is just simply going to be a function that returns a widget right and it's going to be actually a text form field and the reason why we're going to be using a text form field as opposed to just a text field is because the text form field allows us to do some validation checks so we're actually going to end up wrapping um our fields we're going to have a username field and a password field we're going to wrap those fields in a form later on down the road but it's going to allow us to check that form to make sure that everything's valid before we actually try to do anything so now what i want to do is i want to like build out the password field and make it look all snazzy right all right there we go so we updated the text form field that's going to be the password field right and we set it to have obscure text to true because you know you shouldn't be showing off that password and then we have the input decoration which is i'm going to have an icon and some hint text i also added it to the scaffold just so that we can see what this little thing looks like so let's open that up and you can see it up here there's an icon right there and then the password text right here and then if i could get it to trigger which it doesn't look like i can but if uh if i were able to like type in there it would actually obscure the text that's entered in there now the reason why i did this is so that we can actually create the username field which is going to be almost identical to this with just a couple of updates so let's go ahead and copy this password field and paste it and we'll just update it for a username field alright so we have our username field and i actually put it inside of a center column and we have the username field and the password field the only thing that we need to also update is the main access alignment just so that we can um just so that we can have these fields in the center of the screen so we'll say main access alignment center like that so now if i jump back over to the simulator you can see it right here and if i select it i can enter in a pass or a username and then i can also enter in a password which is going to be obscure so really good stuff uh the next thing that i want to do is i actually want to add in the button right so we need to actually be able to submit this form so let's add in a button widget as well all right and now we have our login button as well and that's also going to be in a separate function now um the reason why i'm breaking this out and i'm actually going over it is because later on down the road when we're working with block we're actually going to see that it makes more sense to have each of these things broken out so that we can deal with the state management for that specific uh field or button and it just makes everything really nice and encapsulated and very clean at the end of the day so um as you can see we're back over here and we're looking pretty snazzy only the only thing that i don't like is the padding so i'm actually going to change the center to a padding instead since the fields are actually going to push the uh you know that view to be the full width as much as possible all right so i replaced the center with the padding and if we take a look at it now looking much better in my opinion so there we go we have our form built out now the thing that we have going on right here is that we have like all the setup happening in the build and to make this a little bit more encapsulated and to make it a little bit cleaner what i'm going to do is i'm actually going to create another widget function or function that returns a widget and it's going to encapsulate the entire the entirety of the form because what we're going to end up doing is we're going to be providing the block up here in this area when we build uh the we're going to have like a a login block right so when we provide that we want to do it up here so it's scoped down to this specific view and then we can just take a look at the ui which is going to be the form view all right so as you can see everything is all broken out and chunked up and it's a little bit easier to read in my opinion just because like you can see like this scaffold is going to have the login form it's going to show this right and then we have the individual fields which you can see like the specific things that are going on in there and same thing with the button right so now the reason why we're using the the form is so that we can access the form key which takes uh takes advantage of the state of that form so it's going to go into each of the with the child widgets any of the children and anything that's going to be a form is going to be able to be validated so it's going to check if everything is validated and um that's what we're going to be using the form key so at the top let's go ahead and add a new form key that we could pass into our form so we have our form key right here which is of type global form key and it's generic so we'll pass in a form state right there we pass it to the form itself and then on each of the fields we can go back and we can add in the validator so that's what makes this text form field special is that it has a validator argument so both of our fields now have this validator and as you can see it's it's passing in a value it's pretty much passing in whatever that value is that's entered into the text field so if the username was kyle that value would be kyle if you typed in space then there'd be kyle space and then so on and so forth right so it's passing in that value and then what it's doing is it's expecting either a string or a null the string will essentially say uh that this field is invalid and that um we should be showing a message underneath the field in red but if we pass null then we're saying that this field is valid and there's nothing um further that the user needs to do same thing right here with the password and we're going to actually go into we're going to um add in uh a validator um later on in the in this tutorial but we need to like go through the whole entire uh building out the the login state and things like that so that's all we're going to do for the login ui as you can see there's not there's not a whole lot that actually changed in in terms of the ui but what we want to do is create the login states so we need the login events and the login states so that we can create a login block so what we can do is start since we're going to be building out a much bigger app this is actually going to turn into a social media app let's go ahead and start separating some of these things by like creating a folder called login and we can also create another folder called uh auth and that will contain our login just so that we can keep all the authentication stuff together as well as keep all the login specific stuff together so under the under the login folder what i'm going to do is i'm going to create a new file called login event so as you can see we have this new login event file under the auth login folder and there's going to be a couple of different states that we want to uh or there's going to be a couple of different events that we want to track for our login view right so the first thing that can happen is the username can change so that's going to be its own separate event the password can also change so that will be another event and then lastly the button can be clicked to submit the form so those are the three different events that we're going to be watching for on our login view so let's build those out now the login username changed and login password changed are obviously going to be extending the login event but they're both going to be special in the in the sense that they're going to be um holding on to the value for the specific field that they're responsible for watching so login username is going to hang on to the username and login password is going to hang on to the password the login submitted is just going to be an event that we can just add there doesn't need to be anything passed in so because we'll actually be able to keep track of the username and password from the state so next well let's go ahead and create the login state that's going to be like the counterpart that's going to essentially need to take the event and be mapped to that state let's go ahead and create that file as well so i'll create a new file under login called login state so as you can see here our login state's going to be a little bit different than what we've worked with in the past in the sense that we're going to just simply have a single class that's going to be called login state and it's going to hang onto our username and our password and we create this login state with that username and password now whenever we want to uh say that we updated the username right because you can only update one field at a time whenever you update the username you don't want to have to like go back and fetch the password or vice versa right you don't want to update the password and go out and fetch the username so what we can do is we can also create a constructor called copy with which will allow us to just simply update we can update only one of these values without needing to pass in the other value because we can just simply grab what's already existing there from this class so let's go ahead and create that constructor as well all right and now our copy with constructor is looking to accept either a username password or both and whenever we pass that in we can just simply create a new login state with whatever was passed in however if we didn't pass in one of those values which is going to be the case when we use it then what's going to happen is we're actually going to see that we're going to return the current username for the state so if we pass in the password but we didn't pass in a username then we will simply return this dot username and vice versa now there is one additional property that we're missing on this login state right which is actually the submission so what i'll do is i'll create a new class that's going to be called a form submission so that we can keep track of what the button is supposed to be doing and whether things have been submitted if they're currently submitting or failed and things like that so the form submission status is an object that we should be able to work with on different forms right we don't want to just create a single login specific form submission status just because you know almost all forms are going to be going through a very similar thing so i actually added it under the auth folder but not in the login folder so you'll see that we have form submission status right here and then it's going to be an abstract class that doesn't refer to to login whatsoever now one thing that we do want to change about this form submission status on the abstract class is the ability to make it a constant initializer or a constant constructor because if we take a look at our login state we're giving the username and password default values and we want to be able to do the same thing with our form submission status property so let's go ahead and add that constructor but we also need the other classes which are going to represent the different states of a form submission so we're going to have the initial state right we're going to have the submitting state so that's when we're waiting for the response to go out and then come back and then we're going to have either a success or a failure so those are going to be the different states for our form submission status and we can um sub we can extend our form submission status to uh represent those different states so there we go we have our different uh we have our four different states so we have the initial form status which is also going to have a constant constructor and then we have our form submitting our submission success and our submission failed statuses now this one is going to hold on to the exception in case we want to do anything with it later and we don't have anything on the submission success but if we do decide to change it we can always come back and just revisit here you know we don't know what the future holds so yeah let's head back over to our form state and now we can add in a new property that's going to essentially represent the form status so now the login state represents the username the password and the form submission status and we can see that we're giving it a constant initial form status for the default value when we create a login state and we also updated our copy with constructor to include that form status as well so that we can pass that and you know if we need to make a copy we can do that as well so looks like our login state is pretty much all good to go now what we want to do is we'll want to actually create the login block that is going to be interacting with those two different objects that we created the login event and the login state so under login let's create that login block all right so we have our login block which is going to extend block but we don't have that imported so let's go ahead and go to our postback diamo and we're going to add it in under the dependencies right here so we can just add in flutter block like that and we'll just get the latest we'll save it and head back over to our app and we want to go to the login block right here and now when we import it it should be all gravy right oh that's all gravy all right so now we have our login block still got some red squiggles we'll handle that right now it's going to extend block it's going to take in a login event it's going to map to a login state and we have our constructor and we're giving it an initial value which is that login state which means the username password are both empty strings as well as the initial form status right so let's add in our map to state function as well so that we don't get that red squiggly going and now we can just iterate over the different events that we can have and then map them to the different states so let's do that now so here we can see that we updated our map event to state and we marked it with the async star which means that we're working with this stream and we can yield values out as opposed to returning them right and if the event is login username changed then we're just going to um get our state right which is provided by this block class we're going to copy that state and update that user name and everything else is going to stay the same and then we'll yield that state out right so then we're only yielding out a state that has an updated username same thing with password and the same thing with the field actually being submitted so we're we're handling most cases but as you can see there are a couple of form statuses that we are not covering and that's because we are not actually working with the login repo or the auth repo so what i'll do is i'll create a dummy like auth repo i mean it's not going to be a dummy auth repo but it's like something that we're going to use in the future and build out but we'll create a dummy login function just so that we can represent the other different states in here as well so let's create a new file under auth and call it auth repository so here we have our auth repository under the auth folder right not under login but under auth and we have this login function which is just going to do some dummy functionality right it's going to return a future void and it's going to be asynchronous and all we'll do is we'll just print out to our logs attempting login we'll wait three seconds and then we'll show logged in right just to simulate that that experience and we can kind of watch what happens to our state so head back over to the login block and now what we can do is we can add in or we can require that our login block takes in an auth repository because we're going to be reusing it right we don't want to initialize it in here we want to reuse the same auth repository everywhere so we'll pass in a auth repository to our login block and then we'll also call that login functionality down here in the login submitted event so let's do all that now and there we go so now as you can see we have our auth repository being passed in through our constructor and whenever we have the login submitted whenever we hit that button we're going to first start off with form submitting so that we can like show maybe like a circular indicator or something like that and then we're going to actually attempt to log in now depending on what happens with that login either we're going to be able to successfully be able to continue in which case we'll we'll copy our state and emit a submission success right or we're going to copy our state and um have this submission failed and we're going to also pass in that exception so now we're handling all the different states that we can have in our app and all we need to really do is actually connect everything together so let's head over to our login view which actually needs to be under login right like come on now we gotta keep it all all together so let's keep our login view together and what we want to do is let's start up here at the top right and we're and actually let's start at let's start over here at the main.dart and let's start by supplying our repository because we're going to be using our repository in different parts of the apps more specifically in the login portion of the app or the the authentication portion of the app but let's go ahead and add in the repo right here and then we'll be able to access that repo further down in the widget tree there we go so all we really did was wrap our login view in this repository provider and we're going to just simply create our our auth repository which just simply has that login function in it right but now anywhere further down in the widget tree we'll be able to access this auth repository so let's head back over to the login view and right here in our build method that's where we're actually going to access that that auth repository but we're also going to build out our login block right so now so neo what we can do is we can wrap this login form inside of our block builder which is also going to be accessing the auth repository so let's do all that and then i'll go back in and explain what's going on there we go so we have our block provider because we still need to provide that login block and remember our login block needs to have that auth repo which we can now read from the context and specify that we're looking for this auth repository since we just added it in main.dart and then our child is going to be that login form which means that anywhere in the login form the block builders can now access this login block oh yes so let's go ahead and start with some of the children inside of our column which are the username and the password and we want to update this username field to be embedded inside of a block builder so that we can actually update the state right we we need to um update the state whenever the user enters in a different character for their username field so let's go ahead and wrap this into a block builder so now our text form field is wrapped inside this block builder which is going to have the login block in the login state right and all we're really changing so far is the on changed so what we want to do is we want to get the login block that we're working with so we can do a read and then we can add the event that's happening which is this login username change so anytime this unchanged is called is whenever the user enters in a new character or deletes and then we're going to pass that value into this login username changed right here now up at this point we don't necessarily need the block builder anywhere in here right because we're not actually utilizing any of the state and if we wanted to grab the context we we can just simply do that because we already did provide the login block up above but the important part to use the block builder is for the validation so the validator right here is what we're going to be using the state for now we haven't covered this part yet but back over here in our login state we can actually add properties that will determine whether the value is valid or not so we can do our validation right here in the login state as opposed to over in the ui and have that logic live there so i'm gonna i'm gonna add in two different properties that are going to represent whether the username is valid and whether the password is valid and those are simply going to return a boolean and then we'll be able to check the state to see if the username is valid then we can determine whether to show an error message or not all right so we have these two new um properties which are going to be computed properties just checking if the the username is valid we're going determine whether it's valid or not by saying is the username longer than three characters if it is it is a valid username um same thing with password is the password longer than six characters if yes then it is a valid password now obviously we can build out a more robust way of checking if something is valid or not but we're not going to cover that in this series i mean you come up with all kinds of different ways to validate these fields and figure out if they're valid or not but we're just going to go with length right here to represent that we are validating it and now since it's part of our login state what we can do is we can go back over to well let's say this i don't know why it's sticking out at me but let's go back over to our login view and since we have access to our login state right here what we can do is we can check is this state um is it a valid username and if it is then we can just say null but if it's not then let's go ahead and return a message saying invalid or we could say username is too short right so we already know what the the reason for the validation is going to fail so we could just do something like this or we can make it more generic however you want to go about it so now we're actually taking advantage of this block builder the login state that's being passed to the builder method and we are going to show the validator uh you know when we are attempting to validate our form right here now we did this for the user name field but now we have to do the same thing for the password field so let's add that now so here's the updated version of our password field once again just wrapping it in our block builder same exact block builder login block and login state pass that state in we're going to check if it's a valid password if it is don't return anything but if it is not then we'll return a message saying it's too short and then whenever we change that password whenever the user types something we'll uh send the event login password changed with that value right here that's being passed in so that takes care of our two fields let's go ahead and handle the login button and kind of do the same thing so what we want to do is we want to wrap it in a block builder and then watch for the state to make sure whether we should be showing the elevated button or if we should be showing something like a circular indicator so that the user can't hit login again while we're waiting for the request to come back so once again just adding the block builder here at the top of our of our view which is the login button and now what we're going to do is we're going to return two different types of widgets depending on the state of the form status so if that form status is form submitting then we'll just show that circular progress indicator but if not we can just continue to show our elevated button which is going to be login now what we want to do is whenever we hit the login button first we want to check to see if the form is valid only if the form is valid then that's when we want to actually do the submission right we want to actually do that that submission event for our login but if it's not then we're just going to leave it at that but when we check if the form is valid what it will do is it will trigger the validator in both of our fields to see if these fields are valid based off but based off of our standards right and if if they are not valid then we're going to show those messages so let's add that logic in now so as you can see here we're accessing that form key that we passed into the form and we have a property on it called current state and we can call validate on that that's what's going to trigger any form widgets subwidgets of our form to check that validator function and that's going to have it update the ui now if we get back a true that we're returning null in all validator instances then that's when we're going to read the context for the login block and we're going to add in our login submitted so that's going to handle all of that so we should be pretty much done with everything that we wanted to do let's go ahead and stop the app and run it again and let's see if everything works as we expect it to all right so we have our form right here and let's go ahead and start off with nothing entered in and the user tries to log in we hit login and as you can see the validator was checked in both instances since our state is full of empty strings for the username and password we can see that the username is too short and the password is too short and those are being brought up because of the validator so now if we go ahead and enter in a name like kilo loco and we try to log in again the validator does its thing again we see that it's fine that issue goes away but our other form which isn't valid also is um showing that message still so then we enter in a new password like this we hit login and as you can see uh everything seemed to work as expected in regards to our fields but we never got to see that circular progress indicator and the reason for that is because i made a mistake that's mobby right so we want to go over to our login block and what we want to do is we want to make sure that we're on that we're first emitting this form submitting state right and then we want to do the auth repo login and over here what we want to do is we want to make sure that we're doing this await because we were just doing this delayed without waiting for it to be done um login logged in was called immediately so a little little hiccup in our dummy view but let's go ahead and update this so this is going to be kilo logo right and then in our password we could just do something like password as long as it's longer than six characters we do log in we see our circular indicator we wait three seconds and then it's going to say logged in so everything seems to be working as expected because if we take a look at our login block we were we're currently handling the login username changed the login password changed and obviously the login submitted we're showing that that circular indicator for the form submitting we're showing the success but we also want to check what happens when we fail and the way that we can do that is we can go over here in our login um our login function of our auth repository and instead of just simply doing this logged in we can throw an exception right so we do this exception and we give it a message saying um failed login right something just something to to send back so now if we have this exception in our login block what should happen is we should catch that exception pass it to the submission failed and we should actually see that and we actually won't see anything because we haven't updated our ui to handle that use case right so let's go ahead and add in another username so kilo logo and password like that and we'll do login and as you can see it's waiting it's waiting it's waiting and then even though we're throwing an exception we're not doing anything with that exception so what we want to do is show a snack bar showing that our login did failed and we'll do that in our login view so down here at the bottom i'll add a new function that's going to be responsible for showing the snack bar so here's our show snack bar function which is going to take in a context and a message so the message is just going to be simply passed into a text widget for our snack bar as the content and then we'll access our scaffold messenger of our contacts and we'll show that snack bar so what the the place that we actually want to um run this functionality is when we do receive that failed uh status right so whenever we get that failed status that's when we want to show the snap bar and we can do that up over here in our in our block provider or right here so our login form so we can actually wrap our form in a block listener and the block listener is there for like one-off events that you only want to observe one time like as it happens and you don't want to necessarily access that state later again so let's go ahead and wrap this form in a block listener observe for the the failed state on our form submission status and then show our snack bar so now our form has been embedded inside of this block listener and it is now the child right and for the listener argument once again we're just working with that login block and that login state we pass in the context and that state we access the form status we check if it's submission failed if it is then we simply show our snap bar and we use the exception that's passed to the submission field and we make that a string and that's what's going to be displayed at the bottom of our screen so let's go ahead and give this a nice restart and let's go ahead and enter in our username which is kilo logo and then we can pass in a password like so and we do log in and we wait three seconds and it should fail and as you can see failed login and that's the exception that we're throwing back in the login block so that's everything that we're going to be covering for today i know that was a little bit of a longer video but there is a lot going on in regards to working with the block pattern and using forms now this is what we're going to continue to do as we build out this social media app so we're going to need to build out the you know the sign the sign up page and the confirmation page and then we're also going to need to be able to manipulate our a higher level of state to show the session view right so all of that is going to be in the next coming videos as we wrap up this hashtag 30 days of flutter if you are interested in watching these videos make sure that you subscribe and if you you know if you like the video then give it a thumbs up i'd really appreciate it so that's going to be it for today i appreciate your time now go out there and keep coding passionately
Info
Channel: Kilo Loco
Views: 65,609
Rating: undefined out of 5
Keywords: flutter, flutter tutorial, dart, flutter tutorial for beginners, flutter for beginners, google flutter, flutter ui, flutter app, flutter course, dart flutter, dart and flutter, flutter bloc, flutter bloc pattern, flutter bloc tutorial, flutter bloc tutorial 2021, flutter bloc login, flutter bloc state management, flutter bloc library, flutter bloc pattern tutorial, flutter bloc pattern tutorial from scratch, flutter login page, flutter login ui, flutter login page ui
Id: 2pjzvCDc4L8
Channel Id: undefined
Length: 36min 23sec (2183 seconds)
Published: Sat Mar 13 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.