Flutter Firebase & DDD Course [24] - Note Form Page

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
the time when we start building the last missing piece of the ui is finally here note form page is the most complex widget in this app so we have to divide its implementation into manageable parts let's now focus on everything except for form fields [Music] hello welcome to risocoto where you're getting prepared for real app development so that you will get freelance clients or a job and be confident about the apps you built so subscribe and hit the bell to join us on our quest for becoming in-demand flutter developers so we are going to start off finally building the note form page which is stemming out of the note form state for the note form block which we have built some while ago and because pages are dependent on the respective state of the block with which they are operating even more so when it comes to note form pages or another sort of a form page which we have in this app is of course for the authentication sign-in form page right these two states are very similar sign form state and node form state they are just variations on the same thing we want to have this state working with a form which we can fill in and basically because node form page is going to be absolutely dependent on this node form state it's a wise idea to open up this node form state file because we're going to be looking at it periodically to figure out what to do in the ui which is stemming out of this state from the application layer so just open up application nodes node form node form state and we are going to go from there so let's go ahead and inside the presentation layer for the node form we're going to create a new file over there and let's name it node form page dot dart of course and this is going to be a stateless widget and as i've said at the beginning in this part we are going to focus on everything except for the node form fields so we are going to have the basic skeleton we are going to have the app bar these buttons on the app bar we're also going to implement that when we save a note and it's uh correct so basically there are no errors which means that all of the fields are filled with a valid value we're going to also build in this part this loading overlay which you can see right now and we're also going to implement the fact that when you click on a note the app bar says edit a note and you can also just create a new note when you hit this plus floating action button so let's get to it let's create a stateless widget note form page let's import material dot dart so that the errors are gone and also because we will have the ability to edit a note as opposed to creating a new note we should be able to possibly accept the note entity which is currently being edited into this page if it's passed in we will know that we are currently editing an already existing note if it's not passed in if it's null therefore we're going to know that we are creating a new note so we're going to create final note edited note let's import the note entity and let's create constructor for final fields just like this and let's make the edited note required now would be a good time to actually run the app so that we can see the ui we are currently developing and let's first implement the logic which is going to ensure that actually pressing these buttons and already existing note cards is going to take us to this note form page so we want to go to the notes feature or sub feature should i say and inside the notes overview page over there is a floating action button right here which has a to-do in there saying that we should navigate to node form page so now since we have this node form page already we're going to navigate right so what we want to do is to use the extended navigator which comes with the auto route package and we're going to say off context push note form page which of course does not work because we currently don't have this route defined so of course it would be wise a wise choice to first go to the router configuration file inside routes rower.dart and since we have just added a new page called node node form page actually we should add it as a material route right so we're going to say note form page just like that and actually in the already finished app you can see that we have this x symbol for closing as opposed to the back arrow for navigating back and this is accomplishable with specifying that this note form page is a full screen dialog so we're just going to say full screen dialog true for the node form page save that now because we have edited something which is which has to do with order route we need to generate code so let's use our favorite command flutter power builder and watch delete conflicting outputs once this has run we are going to be able to use the extension method for navigating to the note form page without any issues so here we go we can now try it out so let's go to notes overview page and now there should be indeed a method called push note form page so let's do just that and since we are navigating to that page from nodes overview from the floating action button we are about to create a brand new node so this means that the edited node which we specify over here is going to be null alright with this done we can come back to the app which we are currently developing and when we press on this floating action button we are going to be taken to a new page which currently looks like this it's completely blank and dark because we have not yet built any ui over there but we know that it actually works right now the same thing sort of needs to happen when we press on a note card so let's copy this line which navigates to the node form page and let's go over to a note card widget which is present under notes overview sub feature widgets notecard widget dot dart and somewhere in here there should be a to do of course there is over here implement navigation so whenever a card is tapped we want to navigate to the node form page and somehow it doesn't want to work very well push note form page isn't defined is interesting we probably just need to import our router so let's import routes right if you write routes auto import the router file which we have defined right here then it's also going to make it so that you can use the extension methods because again extension methods are not auto importable as of now all right and the only difference we want to have here is that the edited node is not going to be null but instead it's going to be filled in from the node field which is present on this note card widget okay and with this when we now press on this note card we are indeed going to be taken again to this dark page which is nothing else than our note form page so with this done let's actually go back to this dark page and we are going to start implementing it with some actual ui right first and foremost we know that we need to provide a note form block down the widget tree from here so the first thing we are going to return from here is going to be a block provider which is going to create a block which we can get of course from get it as we have gotten used to uh it's node form block let's import node form block so now this node form block instance is going to be available down the widget tree but this is not everything if we take a look at the node form block and its events we have an event called initialized and if you want to you can always just check out the code from the link in the video description or go over and watch some of the previous parts which dealt with implementing this node form block because it's quite a while since we have touched this code but basically we have this initialized event which accepts a initial note option and we're basically of course going to initialize the block possibly with an already existing node so we definitely want to add this initialized event to the block when we are starting to provide this block down the widget tree so once we get it from get it of course we say add and we want to add this note form event dot initialized and this accepts a initial note option so it's going to be an option off edited note which is this field over here but it kind of doesn't want to work because we need to import darts and now it works so basically if edited note is null it's going to pass in none if it's not null it's going to pass in some edited note for now we are going to make the child of the block provider very simple we're just going to make it a scaffold later on in this part we are going to come back here and add some error handling snag bars over here but for now let's just build simply why with a scaffold without any snag bars so scaffold okay it's already starting to look better than that red error of doom screen but because i already know that this is going to become very very nested if we leave the scaffold in here as it is right now it's a wise idea to extract a widget so let's say extract widget we're going to call it node form page scaffold like this and we have just made sure that we are going to mitigate any nesting which would happen after a while once we are going to begin building the scaffold right so what's going to be in here of course we want to have a nice add bar let's set it to app bar looks good and as you can see because we have made this route to be a full screen dialog instead of that back arrow we have a cross so this add bar will have a title and this title will be of course a text which can say edit a note when we are editing a note like this or it can also say create a note when we are creating a new note so we need to make sure that this text can be dynamically built and how in the world can we do that well of course our beautiful note form state will take care of that we have already implemented the logic which switches this is editing boolean present on our node form state either to true or false depending on whether we are editing a node or not right so we need to read this field from the node form state and based on that we are going to be able to build a different ui for the title so let's go back and of course the way that we can do this with block is by using a block builder so let's say block builder it's going to be well actually let's use the shortcut so block builder if you don't have the vs code extension for blog i highly recommend it so we're going to say note form because it's a node form block and node form state and from here we want to return a text and if state is editing is true we want to say edit a note otherwise we're going to say create a note just like this and now it works right so we can see create a note but when i press on the note card and that's how i get into the note form page it's going to say edit a note so edit the note or create a node and that's pretty cool but we can optimize this block builder a bit because currently whenever the state of the node form block changes this text is always going to get rebuilt but for example if we just update one of the fields for example the body of the node or when we are currently saving the node which means that the full state has changed we don't necessarily need to rebuild this part of the ui because this part of the ui basically never changes once the ui is first built the editing state of the note is never changing so in order to spare some performance although it's really minuscule in this case we can use the build when comparison function which is going to give us a previous state which i'm going to abbreviate to p and then current state which i abbreviate to c and we can decide whether or not to rebuild this particular part of the ui and we're going to say that this should be only rebuilt if the previous states is editing boolean is not equal to the current states is editing boolean and with this done it's basically never going to get rebuilt ever after the first initial build in this case all right another thing which should appear on the add bar is the button to save the currently created or edited note so this is possible via actions which accepts a widget which is going to be a simple icon button and this icon button will have an icon let's say icon icons check and also unpressed needs to be implemented so it will look something like this and unpressed we can get hold of the block so let's say context block note form block and we are going to add the only event which makes sense which is note form event dot saved so this is going to trigger the logic to first validate the note and then if everything is valid then it's going to get saved to firestore through the repository of course in this case because in this part we are now going to be building the nodes fields what's going to happen is that the note will always be invalid so nothing will be saved to firestore why is that well basically we are always going to be operating with a node form state which has an empty note node will always be empty because we will now be able to change the values of the fields inside the note so that means of the body of the note color and of the to-dos and therefore they're always going to be empty and invalid just like in the already finished app when the note body is empty we cannot continue it says cannot be empty we're going to bring this functionality into the app later on in future parts but basically this is what's going to be happening behind the scenes we're just not going to be able to see these error messages popping up because there are going to be no form fields visible what i wanted to say by that is that we are safe we are not going to be spamming our firestore database with blank notes because they are just empty and invalid and unsavable therefore all right now that's it for the add bar now the note form fields are going to be built as the body of the scaffold but as i've said just now we're going to leave it for later parts so let's not touch the body of this page where the form fields would be but instead let's focus on showing snag bars for error handling and also let's focus on showing the saving in progress overlay so how can we handle errors and show appropriate snag bars well right here where we are simply using the note form page scaffold as the direct child of the block provider for the node form block we are instead going to wrap it inside a block listener so actually just a few days ago this functionality was allowed by the state of the dart something i guess it's an issue with the vs code or maybe not i don't know maybe with the analyzer or something but uh you could not wrap widgets with just any sort of a other widget like for example with blog listener but now you can do this right out of the comfort of vs code with just a few shortcuts so now we can wrap this widget with block listener which is awesome the block we want to get is of course the note form block and inside this listener we are going to show different snag bars depending on the possible error and also let's make this note from page scaffold use the constant constructor for performance reasons so we have already implemented this kind of a snag bar error showing thing in the ui before if you're wondering where i know it's been a while ago but we have done this inside the auth we find it well actually not auth it's called sign in of course sign in sign in page i guess actually sign in form and over here we have already implemented this kind of a flow where we check the form states auth failure or success option and if it's none meaning that the user has not yet taken any action we don't do absolutely anything but if it's sum we will take the failure in this case auth failure in the node form page's case it's going to be a note failure we take that possible failure or success of the action performed by the user in this case saving the note and if a failure occurred we show a proper flush bar which is a snag bar but simply done and in the case that the action has been successful so again in this case if the note has been saved successfully we perform some sort of a navigation we just close off the page and do that kind of stuff so we are going to do the same thing inside our note form page if you want to get a refresher a more in-depth explanation to what i have just said just watch the some of the first parts where we have implemented the sign in form page but now let's get down to business so state save failure or success option dot fold and if it's none again we don't want to do absolutely anything because no action has yet taken place however if it's sum first stop we want to give this a better name so instead of a we are going to call this either either like this because it indeed holds either a note failure which indicates failure or unit which indicates successful saving of the note so we want to make this into a block body like this and now we want to get hold of this either and fold it so if there is a failure in this either what we want to do is that we want to show a flush bar a snag bar so in the case of a failure we are going to again create a block body it's getting heavily nested already but this is the thing which we have to do and we are going to say flashbar helper helper dot create error and there will be of course a different message for the error snag bar depending on the note failure which has occurred and of course there are multiple note failures which can happen so we're going to say failure map and we want to map all these different cases to different messages if this was a production great app which you would want to release on google play or the app store or wherever or flutter web you would of course use some sort of a localization over here so that those messages will be localized to a given language of the device but here again we are just going to hard code all of these messages and in order not to bore you to death with me typing out these strings which are quite long i'm actually going to copy and paste them from the finished app so if you want to get this code definitely check out the link from the video description we are just basically going to say this and i have just noticed that we have made some sort of an error because in our case the parameter is not called insufficient permissions but instead just a singular permission this doesn't seem correct but in order not to waste time right now by renaming this thing across many different files especially since it's a generated thing it's a freeze union we're going to for now leave this grammatical error in place maybe we are going to fix it later but this does not change the fact that we have just taken all of the possible failures and turned them into strings which are going to be presented to the user via a flush bar of course after we say show on the flush bar like this all right but how can we test this flush bar when we are not going to get any errors because we have not yet implemented the node form page fully we don't have the fields which we can fill in well the simplest way to do this is to edit the initial state right so if you take a look every time that this node form page is created we get hold of a new instance of the node form block which by default has its state set to be this initial node form state so if we change this node form states say failure or success option from none to sum let's say left of course because it's a failure and the failure will be note failure insufficient permissions let's make it constant like this when we do this now the initial state holds this kind of a failure and when we close off from the node form page come back you can see that immediately we get this sort of a snack bar which is nice so we can see how it looks like and we know that the snack bar indeed works now that we know that it works let's bring it back to none for the initial state of the node form now again we do not want this block listener to run for all kinds of state changes we want this to run only when the safe failure or success option has changed so we're going to say listen when previous state and current state so p and c and we're going to say listen only when the previous states say failure or success option is different from so doesn't equal the current states say failure or success option that's it and then in the case that saving the note has been successful so we don't have any flashbars to show we instead want to close the note form page so that the user will be taken to the notes overview page where they will be able to see their newly created note right so in order to do that we are going to say that if there is no failure but instead we get a unit from the either we are going to again get hold of extended navigator of context and you would think that we can just say pop which would take us to the previous route and that's actually true but also not true in its entirety because even the flush bar is really a route so in the rare case where you would have a flash bar showing on top of the bottom of the screen and then you would call pop you would not actually be taken to the notes overview page like this the only thing which would happen if a flashbar is shown is that the flush bar would be hidden but you would not navigate to the previous full page so in order to always navigate to the previous full page to the notes overview page even when a dialog or when a flashbar is shown on top of the current page we need to say pop until and this pop until takes in a function predicate which passes us a route and returns a boolean to indicate when to actually stop popping and we want to pop until the route which is trying to be popped has name so route that settings.name equal to routes which is our routes defined by us for the order route and over there there is a route called notes overview page all right and this is the page which we do not want to pop all of the routes before we get to the notes overview page we want them to be popped by this pop until so far so good we are actually never going to arrive over here because as of now because it's always going to be unsuccessful the saving of a node because the node is currently empty which is its invalid state but once we implement the node fields we're going to be able to pop to the nodes overview page after hitting this save button lastly what we want to do right now is to show a safe in progress overlay like this if you could see it for a brief moment saving and the screen got dimmer darker and in order to show something on top of something else in flutter we need to use a stack and how are we going to know whether to show this saving overlay or not well again we have a field inside the node form state which is called is saving so we want to use a block builder to rebuild the ui which is affected by this saving overlay so what are we going to do well we want to wrap this note form page scaffold inside a stack with children so let's actually wrap it with a column change it to a stack and in order to show something on top of this note form page scaffold and its contents which is later on going to also contain the node form fields what we need to do is to put the widget which we want to display on top below inside the stack children property list of course so if we do something like container color colors black as you can see now we cannot see actually anything but when we comment it out we are going to be able to see our beautiful ui but of course we want to enrich this container with a loading indicator and all that but also we want to make this container to dynamically either turn on or turn off be displayed or not depending on this is saving so we need to use a block builder right we are inside a blog listener so we are going to create just even more nesting by creating a new block builder widget here and we are going to be nested till the end of times well thankfully we do not need to create it another block builder widget what we can do instead is instead of block listener we can say block consumer and with this we now don't have a child let's cut it out but instead we have a builder which provides us with context and state and from here we can return the stack which we have just created just like this it's wonderful but of course again we do not want to rebuild this part of the ui which is actually going to be quite expensive to rebuild just on every single state change for example we do not want to rebuild this when just a single field for example the note body field is updated by the user that would be completely crazy and expensive to do so because of that we want to again provide a build when for previous b and c current state and we want to rebuild this part of the ui fully only when the previous states is saving is not equal to the current states is saving like this and now we are being considered of the resources and not wasting them just as we go now for the actual container because we of course just cannot leave it as this and we also need to make it dynamic to the is saving boolean so let's go to this container and i'm going to say extract widget let's call it saving in progress overlay like this now we have it created over here we need to pass in a final ball is saving let's add it to the parameters and let's make it required and let's immediately pass in this boolean so is saving is equal to state from the block is saving now how can we make this container to be transparent when we are not saving but have some sort of a black color when we are saving of course it's not going to be fully black it's going to be a bit transparent well there are multiple ways to do this but if we want to have this nicely animated so it's not just going to pop in here fully black and then come out of the screen so that it's fully transparent we want to have some sort of an animation instead of using a regular container we are going to use an animated container currently we have an error because we need to specify the duration parameter which is required so the duration for the animation let's say that it's going to be cons duration milliseconds 150 that's what i found to be a good number and of course the color should be dynamic so we are going to say is saving and if it is saving we're going to say colors black with opacity 0.8 otherwise it's going to be fully transparent so colors transparent cool now because we are not saving you can see that it's transparent by default but how can we actually build this ui if is saving is always false well one option is to just say is saving here to be always true so discard this is saving boolean for now or other option is of course to go into the node form state and edit the initial state but i think that editing the boolean directly inside this widget is the better option right now because it's just more visible here let's however deal with the elephant in the room right now because now it kind of makes sense that the widget which is below the saving in progress overlay is not tappable right note form page scaffold and these buttons on the app bar are not typical which makes sense because the overlay is turned on however if we make the color to be transparent so we say false now the overlay is seemingly not present but we still cannot tap these buttons over here so what can we do well we can wrap this animated container inside another widget which is called ignore pointer and we're going to say ignoring to be equal to not is saving and actually let's make the color also dependent on is saving and we're just going to change the value of is saving actually let's create a same named final is saving so there will be some shadowing going on name shadowing but at least it's going to work so is saving is true just like this okay cool so now we cannot tap it when it's false now we can tap it which is what we want it so let's make it back to true so that we can see what we are currently building and there's not going to be just this kind of an overlay but of course we also want to show a loading indicator so we are going to add a column here as the child of the animated container so it's going to have children and let's say circular progress indicator will be here let's make it constant so it currently looks something like this what's going on here i don't understand right well what's going on is that since we have just added a real child of the container it's now not being stretched to the full available width and height available to this animated container widget inside of its parent now it's actually taking the size of the column which is its direct chart so what we can now do is that we are going to say cross axis alignment and we are going to say stretch but now it again looks kind of weird doesn't it i mean this circle of progress indicator is just completely stretched too so that's not cool either so instead of doing this what we need to do is to just set the main axis alignment to be center like this so that the spinning circular progress indicator is in the center vertically and in order to again stretch this whole animated container across the screen what we need to do is to set the width of the container to be the full screen width so what do we want to do we want to say media query of context and set the size or actually get the size and width which is the full width of the screen and nothing happens why is that let's check out the debug console well we are not going to see anything but what's happening is that we also need to set the height so height like this and now once we have set both dimensions both width and height this animated container is actually going to fill the whole space which the screen offers which is precisely what we want we want it to take the whole screen up or take up the whole screen phrasal verbs now just a very light cosmetic touch in addition to having just this circular progress indicator what we want to have here in addition is a text which says saving but if we add it over here just like this it's going to look horrible i mean what's going on well the reason why it looks so horrible and i'm not sure why the circular progress indicator stopped spinning but that's probably a different issue but the reason why it looks so bad is because we are not within a scaffold the scaffold is in an entirely different widget we are just inside a stack and when you are not inside a scaffold you don't get the themes automatically so what we need to do is that we need to fetch the proper text style from the current theme ourselves so we're going to say style on the text widget and we're going to say theme of context text theme and body text to and we want to copy this with a different color so color colors white cool and also we want to make it a bit bigger so font size it's going to be 16 like that looks cool and let's also add a bit of a spacing from the circular progress indicator so we're going to say const sized box with height equal to eight awesome so now with this done we can remove the is saving variable which is here only for shadowing the one which is a field and actually we are still not done as i can see because what's now happening is that uh even though the animated container is animated away it's now transparent we are still showing the circular progress indicator and also the saving text so what can we do about that well we need to wrap this column inside a new widget visibility and we're going to say visible set it to is saving so only when we are saving we want this column to be visible together with its indicators and now it's hidden and of course we could use this visibility also directly up here wrapping the animated container itself why we are not doing that well because then we would lose the nice animation of going between this black with 80 opacity to transparent so in order to have this nice transition with this 150 millisecond duration we just cannot use this visibility directly on the container itself but only on the child awesome so that's it for this part where we have built quite a substantial amount of the ui for the node form page but actually it's still a long journey to go because we need to build the ui for the form fields and especially with to do's it's going to be quite challenging to build them so you have something to look forward to still in the next parts so definitely subscribe if you haven't already and also join notification squad by hitting the bell button to make sure you grow your flutter skills because here on riso coder i am determined to provide you with the best tutorials and resources so that you will become an in-demand flutter developer and if you are serious about becoming a great flower developer who can build real apps for clients or at the job go to flutter.education link is also in the video description by the way to get the top curated flutter news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best photo resources delivered weekly right into your inbox so if this video helped you give it a like and also share with other developers who are going to find it beneficial too leave a comment if you have anything to say and see you in the next [Music] you
Info
Channel: Reso Coder
Views: 3,528
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, flutter firebase, flutter firestore, flutter firebase auth, flutter firestore tutorial, flutter firebase tutorial, flutter architecture, flutter architecture patterns, flutter domain driven design, flutter ddd, flutter database, flutter todo app, flutter todo app tutorial, flutter todo app firebase, flutter app tutorial, flutter app example, flutter clean architecture, flutter bloc
Id: stMH95E29U8
Channel Id: undefined
Length: 49min 17sec (2957 seconds)
Published: Fri Aug 14 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.