Firestore CRUD with Flutter, Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome back to the channel today's video we're going to start a two-part series on firestore crud operations just did a video not that long ago on this but they went and changed everything about uh the api so i'm gonna come back and and do it with the new syntax uh this will be a two part series and the way i'm gonna split this up is part one will be the crud operations so we'll create a model we'll create a service with all our credit operations we'll connect our firebase project to our flutter project and basically cover everything about crud uh in that in this first video second video will come back and complete it and make it a full-blown application i say full-blown very simple application it's going to be a journaling app that looks like this you can write an entry you can assign a date you can go back change your entry change the date uh and also delete it so if you want that more full experience following it through and getting that user interface that's what part two will be for uh if you don't uh and you wanna also see this in action well we'll have a github repo at the end of part two you can pull down the whole app uh and then play with it uh play with the different crud operations from there so that's what we're doing in this two-part series let's go ahead and get started all right so we can get started by creating a flutter package so i'm gonna type flutter create and i'm gonna use the dash dash org flag here and my org is gonna be com.julo you can put in whatever you want there or you can omit that the reason i'm using the the org flag is that when you go to take something to production you do have to set a real bundle identifier and get away from the one that's automatically populated in the demo app um that's kind of painful to do particularly on the android side and if you've mixed in firestore or firebase then you have an extra step of going and changing it in there as well so if you intend to use firestore you might as well go ahead and set a real package identifier and that's why i'm going to do that there and i'm going to name this journal app and actually i'm going to do journal underscore app because dash is not valid in flutter all right so while that happens i'm going to go to my firebase console so i'll go to firebase.google.com if you don't yet have an account you will need to set one up we'll go to our console and i'm going to add a new project i have created a demo here journal app i've deleted that it's still there i think it's taking some time to finish itself but i'm going to try to create another one and this is where i want to use a hyphen i do not want to enable google analytics at this time if you'd like to you can go ahead and do that there'll be an extra step there all right we'll let that do its thing in the meantime i can see that the flutter project has been created so i'm going to use visual studio code and i forgot to cc cd into the app before i did that so let's do this let's close that let's cd into journal app and then do this so i don't have every project in my practice folder open at once that's better uh looks like this has finished in the meantime so i'm going to go ahead and click continue and i want to just get myself a cloud firestore database set up so over here on the left side i'm going to click cloud firestore i'm going to have an option to create the database here and i'm gonna do it in test mode and i do not wanna mess around with authentication in this app i just wanna keep it simple um so test mode means that basically anybody can read or write into your database which is not something you want to go to production with but it is fine for development and then it allows you to get started without dealing with authentication all right so there's my collection it has nothing in it that's fine here's my application it is just the demo app right now that's fine we need to connect these two to each other so with the recent changes to the api for dart and flutter for firebase um unfortunately the documents in firebase are not as up-to-date as they could be yet but i still think this is the best guide here uh for connecting the two uh connecting firebase to to flutter so what i'm going to do is i'm going to click on docs and i can click either get started for android or get started for ios it doesn't matter because what i'm actually looking for on this page is the fly down over on the left that says add firebase with a framework and so i hit that fly down and flutter is the only option so if i click on that i'm going to get a series of instructions for connecting ios and then if i hit the chip here um it's going to give me a series of instructions for android and these are probably the best set of instructions i have found yet for this so i'm going to start in android and the first step that they detail up here is to create a firebase project and we have done that right here um the second is to register your app with firebase so we have not done that so if you click on your project overview it takes you out here to your main page of your project and you have this option up here for adding a app to the firebase project and so i'm going to click android right here all right and so this is where it's going to ask me for a package name this is what i was talking about with the org to try to get this to be something that is unique so for android it uh generated one for you it's in the android folder it's an app it's in src it's in main it's in this androidmanifest.xml and it is right up here at the top package.com.julo.journal.app so that's where we can get it if you wanted to change it there is more involved than just changing it here unfortunately but this is the readable version of what your package name is right there so we can paste that in we can skip the optional nickname we can skip the optional debug certificate because that is for google sign-in and some other options and things we're not going to use so we can click register app that gives us the option to download google services json which we want to do all right and then from there you can skip the rest just next next until you're out and back to the console and you can see your android app is here we need to find that uh google services json that we just downloaded and we need to drag it into android app so right inside that app folder drag it there it should not be named with this one i always have a few of these kicking around i'm going to delete them while i uh thinking about it so if you ended up with a one or a number of fixed there let's just take that off it should be google hyphen services dot json like that all right so with that going back to our instructions we have now registered our app with firebase that is step two step three is to add our configuration file we just did that by dropping it into that app folder then we need to check our build.gradle files for some values and so we want to start with the application level one which is the furthest one out so this one right here build.gradle and we're checking for a few things so first of all we're checking that google exists in the repositories and it does we're checking that this com google services exists in dependencies which it does not so i'm going to grab that copy it i'm going to paste it right after this kotlin class path here and then lastly we're checking that google exists in repositories and it already does so we're all set there next we want to go into this inner build.gradle the app or the module level and we are simply looking to apply this plug-in here so i'll copy that and we'll just put it right after the gradle plugin actually i think i will just keep it organized and put it right there because this is where the plugin section ends don't think that matters um that's for that's all for the instructions but i can tell you from experience that once you mix in a few firebase plugins most of those will not work prior to sdk 21 so do yourself a favor and bump up sdk the minimum sdk version to 21 at this point all right and the last step is to add our plugins that's the last step for ios as well so i'm going to jump ship over here to ios at this point and we need to create our firebase project done we need to register our app which we have not done with ios so we can add an app at this point click on ios and we're looking for the bundle id which may be different from the android app identifier so what i'm going to do is i'm going to open xcode and i'm going to open that project now if you're not on a mac unfortunately you're just not going to be able to set up the ios application you'll just need to do android but if you are on a mac and you have on a mac and you have android or xcode installed you can go to development you can go to source i'm sorry you can go to your project i'm bringing you through my uh my app go to your project wherever it is whatever it's called um and look for ios and we're looking for runner.xcode.or xcode proj all right and if you click on runner and we go to the general tab you will see at the very top a bundle identifier and you can see that is slightly different from android that's fine android and ios don't have to match but whatever's in here needs to match what's in firebase or there will be no connection there and these are optional so you can skip these and register the app those are easy enough to come back and do again if you want to that gives you an option to download google services info plist do that and let's come here to xcode and take that download and put it right in the runner folder like that you'll get a pop-up leave those options as r and click finish if you try to do that in visual studio code something just doesn't quite click a lot of times so do that in xcode and once you've done that next code you are done with that ide and you can close it all right you can click through next because none of this is anything we're going to have to do here you can continue to the console see that you've got your ios app head back to our instructions and we've completed step two we've actually completed step three by moving those uh moving that info p list in there and now we just need to do the plug-ins and that's uh that applies for both um ios and android so let's go to pub.dev and we need well we need one package to connect it to firebase and that is firebase core so we're gonna go to installing and i am dealing with version .5 and up the directions for 0.5 are below 0.5 before 0.5 are different i have a different firebase crud video on how to do that with the syntax from before firebase core 0.5 and you can refer to that all right so i'm gonna go to pubspec.yaml i'm gonna come down here to below cupertino icons i'm gonna paste that in um i accidentally got a space in there i took it out make sure that lines up exactly on the left side with firebase core because the emel's real touchy like that all right so that's that's the one we need but we can't really do much with just core so we want to also get cloud firestore so we can do our cloud operate crud operations so go to installing make sure you got dot 14 or above if you are trying to match to the firebase core 0.5 and above [Music] all right and if you're coming from previous versions of firebase core this was enough to connect the two but there is now one more step that you need to do you need to initialize the firebase project in your flutter app and that's something that you you end up doing in most apis but flutter used to handle that for you and it no longer does with this new upgrade so that needs to happen so we need to go a little bit into our presentation logic here and what i'd like to do is i'd like to just take out in lib main.dart just want to take all that out entirely and in the lib folder i'm going to put a new folder called src and i'm going to put the app in there so a new file and i'm going to call it app.dart and what i'm just going to have the main.dart do is just run the main dart function and then call the app class from there so in app i'm going to create a stateless widget so i'm just going to use the stl shortcut and i'm going to call it app and we'll just make sure we import material and so instead of the container as they give you in the boiler plate i'm going to create a material app here [Music] and for a home screen i'm just gonna do scaffold body with a center widget and a child with a text widget that says home page so just something on the screen there [Music] [Music] i'll just go ahead and give it a theme not necessary to the back end portion of this i know but let's just do an accent color of colors dot pink accent primary color we'll do colors dot black and that's good for now there we go let me format that all right and then so in our main.dart instead of my app we can do app and i'm just going to change in test there's a call to my app so i'm just going to change that to app and import it that's not a show stopper but at least get rid of the red there all right and the reason i want to do that is i always find this when i build a production app to separate out the app is a good thing um and i think with the new setup for firebase uh it makes even more sense because you end up needing to wrap this or to put some some logic before you run the app and i think it makes more sense since cleaner if you have extracted the app into its own class all right so here's the last thing you have to do to get firebase initialized is you do widgets flutter binding there's actually a few ways to do this i find this one to be the easiest way we ensure that they're initialized and then we await firebase dot ensure initialized all right and so that means because we're awaiting that means that our main function now needs to be asynchronous so we'll tag that with the keyword we'll import firebase core um whoops i copied from above they're not ensure initialize this needs to be initialize app like that all right and with all that in place i'm just going to fire this up all right and there it goes i've got no errors in the console everything seems to be running just fine so for the back end portion of this um i would like to put it all in a service to keep it all night nice and clean so in my src folder i'm going to do a new folder called services and inside of services i'm going to put a firestore underscore service dot dart and that's a class of firestore service and so this is where every interaction with my database will take place when i build this app i'm going to build a provider layer that is going to directly talk to the service and then the provider layer will also talk to the view so the view is never reaching into the service all right so up at the top of our service this is a little bit different as well so i think you're used to putting firebase up here so instead of firebase we want to bring in a firebase firestore instance which i will need to import i'm going to call it underscore db and that is a firebase firestore dot instance like that so that gets to gets us an instance of cloud firestore i think it used to just be firebase uh instead of firebase firestore so slight change there we're gonna have uh a series of journal entries that we're going to want to get we are going to want to insert update and delete we'll call that create just so we have our crud right there all right and i would like my service to have this all modeled out for me so when i go and get something from the service i'm getting back a list of my journal entries i'm passing in a journal entry to be created or updated um and so i need to define what that entity is and i'm gonna do that through a model so in my uh folder src folder i'm going to create a folder called models and i'm going to create a new file in that called entry.dart and this will be where i define my model so we're going to create an entry class that's our journal entry we're going to have variables so i'll have a final string which is my entry id i'm going to have a final string which is my date i'm going to store dates in firestore as iso strings i can then parse those right into date time in dart and i can just call to iso string from dart to get it back into a string so i find that works best when working with strings and fires or working with dates in firestore store them as a string and then work with them as dates on the dart side and then lastly we'll have our entry which is our our actual journal entry [Music] i'm going to build a name constructor for that so i'll do this dot date this dot entry this dot entry id and anytime you work with firestore so you want to be able to not only define your your object but when you have that object and you want to send it on to firestore you're going to need to convert it into a json object and when you get it out of firestore you're going to need to convert it from a json object into your dart object for work in your application and so you need two functions that do that for you in your model and let's take the first one which is where we're getting json from firestore and turning it into our object so we're going to build a factory constructor so we use the factory keyword we can define what our extension is going to be called and i'm going to call it from json and i know what i'm going to be getting as far as dart is concerned as a map with string keys technically they're all string values but i prefer to use dynamic here just to keep it flexible and that shouldn't be jason it should be json all right and when i get my json i want to just pull each one of that out and or and map it to a property in my object so i'm going to return an entry and so the date i'm going to get from json date entry i'm going to get from json entry and entry id i'm going to get from json entry id now these are just simply the names of the fields in cloud firestore which don't yet exist but what i intend to do is to create them with the exact same names of my properties so if i was working with a database that already had you know entry underscore my i would do that and i wanted it to match entry here i could map it like that but i'm gonna plan on the fields in my database exactly matching what i've set up here in my property all right so that's one way the other way we need is to take uh the object and turn it into something we can send on to cloud firestore so that's going to result in a map with string keys dynamic values and we'll call it to map and we will have it return a json object going the other way so this will be what we end up with for a column name in uh cloud firestore or a key value in cloud firestore and this is the value that we will populate to it the date from up here entry entry entry id entry i [Music] do and that is our model define our fields create a constructor and have two methods that take it from uh two and in two into and out of a dart object from json all right so now that we've got our entity defined i can come back here to firestore and i can say all right if i'm going to get a list of all the entries i'm going to be getting a stream from firestore uh i could get a future back if i want to so firestore opera offers the option of selecting a stream or a future with the app i've got a stream of my journal entries i think makes the most sense on the front page and so i'm going to get a list of my entry objects and make sure i like double close that bracket there we'll call it get entries all right and so we're going to return from db i'm just going to put every operation on its own line i'm going to get from a collection i i'm going to call my collection entries and i this is where i have the option i could say get get which would return me a future or i can do snapshots and get a stream and i want to get a stream and so this is going to get me a streaming query snapshot so i actually want to map that and i'm gonna call it a snapshot [Music] so now i've got a query snapshot on those are docs and so i actually want to map each one of those docs as well and now i have that query document snapshot which has a data property with all the data in it which i can pass so i'm going to do entry and a call from json doc data like that so this contains all the json right here this data we pass this to our model from json property and it's able to take that json because we defined that and turn it into our dart entry and then we don't quite have a list so go inside of the last parentheses and cast it to a list and then you're ready to follow that up with a colon and that will allow you to get a list of our collection from firestore cast it into a list of your custom object not technically part of crud but still good to know um if you wanted to query in here you could do that so this is where you could jump in with where date we could say is greater than datetime.now we could say all right we're going to add a duration of days minus 30 and we'll cast that to an iso string like that so this would say okay only give me entries in the last 30 days oops i don't want to semicolon there and anything older than 30 days you wouldn't get out of that collection so you could do that there if you wanted to all right so for our create and our update so what i like to do is to just combine the two into an upsert all right i i this is this is my preferred method of operation here and this will say all right if the record doesn't exist go ahead and create it uh if it does exist update the fields that i'm providing and if i'm not providing certain fields uh leave those alone all right so there is a specific update function uh in firestore um but i'm thinking that the set data with the options which is what i'm going to use um i'm thinking that that's going to be what they hold on to just because with the options you can do so much more uh whereas the update just kind of does one thing maybe they'll maybe they'll keep the update in the mix but i'm kind of banking on the set options in the future here all right and so regardless i'm going to get back a future void and i'm going to call this set entry because i don't want to give the impression that it's an insert or an update and so what we can do is we can pass in our object now this object we could because we've made our fields uh non-required we could omit the date and just pass in the journal entry we could omit the id um actually we're going to need the id for purposes of identifying the record let me show you here so what we're going to do is we're going to return db collection and we're going to go into our entries collection not that all right so and then we're going to go and look at a specific doc reference this used to be document so doc is the new new syntax and what we're going to do is we're going to look in the entry id so that if the unique identifier already exists we're going to get that record and then we're gonna set entry and we have an entry object we have our two map function which we created which will take it from the dart object turn it into json because that's what firestore wants to see and should not have a semicolon there alright so this as written is a create function only this will overwrite anything that we pass in so if we pass this without the date for an update it would simply drop the date and that's not what we want so up here at the top we can create an options variable and that is going to be a set options class and in here we can merge and set that to true and then we can pass in those options here so what this this is going to do is if we are creating a new entry um it's going to take the entry id that we give it and we're going to write in our provider a function that will get a unique id for it and pass it in it's going to pass that in we will create a new record at that entry id when we go to update it's going to find that record and it is going to take the fields that it has in this entry and it's going to update those fields if we omit say the date and we just update the entry the writing from the journal for that day because we've set merge to true when we go to update we're just going to update the entry field and the date that is there will stay if we set this to false or we had just left it without any options the new object or the end the object we passed in would overwrite what was there and so the date would disappear because it's not on our update but by setting merge to true we are creating the ability to add a new record or to update a record and to not take out any fields that we choose to omit if you want different behavior you can set it accordingly through your your merge options but that's the behavior that i want that's an upsert behavior all right then so lastly we need to delete and this one's pretty simple we want a future void i'm going to call it remove entry and i'm just going to pass in the entry id and we'll return db collection and the dock will be the entry id so we'll make sure we have an entry id field that matches our document reference and then we will simply delete alright and because we are actually needing our entry id to identify our object here like i said we could omit fields here um and just simply have them not updated but if we omitted an entry id we'd really be in trouble because we couldn't identify so what i'm going to do here is just come inside my constructor and say when you construct an entry this is required and that requires an import from material [Music] like that and that way whenever we create an entry object we can omit date we can omit entry if we're just updating those but we can never omit the entry id which we need to identify that in the record all right so that is essentially the crud part of the application in the new syntax for the dart api for cloud firestore and for firebase and so if you're only here for that i want to let you go at this point we'll wrap up this episode and the second episode what i will do is build a provider which will act as the intermediary between our screens here and our firestore service and we will put these into play you can start to see them in action we'll populate our database and go from there and we'll come back and play with these options a little bit so that you can visually see how options like merge equal true false uh how these queries in here uh interact with the screen so that will be part two of this series should you care to join us but thanks for watching this one hope you found it helpful
Info
Channel: Andy Julow
Views: 17,484
Rating: undefined out of 5
Keywords:
Id: zaiE08EWrO0
Channel Id: undefined
Length: 37min 52sec (2272 seconds)
Published: Thu Oct 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.