Video details

The Best 20 Minute Angular & Firebase Video You’ll Ever See

Angular
06.08.2020
English

David East

Watch all the ng-conf: Hardwired presentations/videos at www.videos.ng-conf.org.
ng-conf is a three-day Angular conference focused on delivering the highest quality training in the Angular JavaScript framework. 1500+ developers from across the globe converge on Salt Lake City, UT every year to attend talks and workshops by the Angular team and community experts.
Follow us on twitter https://twitter.com/ngconf Official Website: https://www.ng-conf.org/

Transcript

This is not an episode proves I'm actually here today to teach you all about Angular and Firebase. My name is David East. I'm a developer advocate at Google on the firebase team. And for this talk, I'm taking a moment out of my work from home schedule to give you the best. Like I was saying, I'm taking a moment from my work from home scheduled to give you the best 20 minutes angular and firebase video you will ever see. I think. I mean, Jeff Delaney and Firesheep, I know he makes really good videos, but maybe none of them are exactly 20 minutes anyways in this video. I'm going to take a hands on approach and I'm going to show you some amazing things you can build with Firebase and Angular. So what is Firebase Firebase as a platform for building powerful apps fast? You just include a JavaScript library into your app and you're connected to a hosted back end without needing to build it or host it yourself. So get ready. We're going to go from zero to 60 really quick. I'm an. Lego saying, get ready. We're going to go from zero to 60. Really quick Furbys comes with the JavaScript library that knows how to connect your hosted back end. You import the module and then call the initialize app method with configuration you get from the firebase dashboard. This is all safe to put in your app. No private keys here. Now this isn't do anything but tell my app how to connect to Firebase. So let's synchronize data in real time with one of our databases via store. Firestar is a document database, which means you have collections and you have documents and a collection is just a list of documents. So to get a single city, I'd tap into the collection of cities and grab the document by its I.D. And then from there, I can call on snapshots to read this data in real time and every single time this data is updated in the database. This callback method will fire off with new data and from there you can just query any element from the page and then you can bind that update to The View. And you can see this is just a Jason object, and every single time it updates in the database, we'll get that instantly on the page. Now, some of you Angular and ARC's jazz fans might be looking at this callback method and think to yourselves, this looks pretty familiar. And actually, we can return from this on snapshot method and it gives us an unsubscribe function. So some time later down the line, if we wanted to stop listening in real time, we could just call on sub. And this is just like an observable and that is why we built angular fire, angular fire is the official library for Angular and Firebase. It brings together angular firebase and arcs, Jess and one library to make building things really fast. All right. So we just went from zero to ten. Now we're gonna go from 10 to 30. Therapy. Cheryl Soubry. One second. We just went from zero to 10. Now let's go from 10 to 30. Let's make it to do it because you have to make it to do. My main module, I'll import from angular fire and initialize mine needed and G modules I can call initialize app and I'm going to use the environment section of the angular selye and I'm going to import from the angular Firestar module as well. And this gives me everything I need for dependency injection. This project is already setup with the router and we're getting back some rep parameters which are help us read from the database so I can inject the angular Firestar service so we can talk to our back end. So the way that this project is set up is that we have a top level collection of projects and each project is a documents and documents can actually contain collections themselves. And these are known as sub collections. And this is where our to dos live in the tasks sub collection. This returns to us a collection reference which allows us to update, modify and read data. This location, which can actually be done with a generic as well. And to read this data, we're going to do it as unobservable of tasks and array in that case, and the collection reference has a bunch of methods to read the data back as an observable. And so we can take this observable and then bind it in the template. So in this unordered list, use the engy if as trick to pipe the task back and then just iterate over them in the ally with Engy four. And each task has a title. And just like that, we have the data bound in the browser. But what's the to do list app without adding tattoos? So somewhat you use this input bar, which is just an easy way for me to have a text box with a button and to be able to get the text back through this new value output. And then back inside of the component, I'm going to move the task collection to a property because this will allow me to use it in the on new task method. And we can actually do this as a generic so it knows what needs to be added. So inside of our new task, I'm going to add the new task by calling the ADD method. And this knows that it needs to be a calm task. So it's going to yell at me and so I have the correct day to type. So in this case, I need the category of not started. And then some dummy user data. Now, when I enter a new task and hit the create button, it automatically updates on the page. But this is just too simple. We all know that tasks have intermediate states like not started and in progress and also done. And of course. Done. Done. You know, like when you say some things done, but it's not actually done, so you need to polish it up and write some tests. So it's done. Done. And just like that, we have a combined board because if you stop and think about it, most apps are just to do apps in disguise. Since these tasks are just an observable, we can do some ARC's Jass magic instead of returning a single array of tasks, will return an object of arrays and each key of the object being the category as in not started or in progress. And our X makes this very easy. We can just use the map operator to create the object. Iterate over each of the tasks. Make sure that there is at least an empty array or the existing array, and then just add each item to the array. And this updates every single time that the data's updated in the database because observables and fire store work very similar. And this is still unobservable. So we can use the engy if as syntax to unwrap the new object of arrays and then just bind each object to the tasks inputs and then to give this an extra bit of pizzazz. We're going to wrap each list with the angular c.D Cays drag list. And the angular CDK makes this super easy. We just make sure we pass all of the inputs and provide the right outputs and do that for each one of the columns. Then we just need to let the component know when something is being dragged and dropped. So on a drop event, we make sure it's a new container. Get the transferred item, the category by the I.D. and then all we have to do is find the item in the database and then update its category. Now, when we drag, we're getting an error, so opening up the console, you can see that it can't find the I.D. So when you're using value changes, this just pulls back the data and not its corresponding document I.D.. So using I.D. field, we can map that onto the data. So now pulling up to browser's side by side, if I drag a card just like that, it updates in real time. A vital part of any app is authentication. Firebase authentication gives you a lot of different ways to authenticate your users with just a few lines of code. And just a few lines of code angular fire comes with two of the modules. The core angular fire off module and also the angular fire off guard module. The core module has methods for logging users then and monitoring their logged in states. And the guard module allows you to protect routes and off. And the router tend to go hand in hand. So in this case, we're going to want to log a user in with Google and that is done with a redirect and that can make things a little bit tricky unless you're using the router. So in this case, I'm going to call a sign in with redirect method and give it a provider. So here's the trick. Calling sign in with redirect won't ever return the user you're trying to log in, and that's because that will call up to the third party providers log in page and then that calls back to yours, meaning you'll never get to any code beyond line twenty three. So the way you fix this is by getting the redirect results. This resolves a promise that tells you whether a user has come back to the app through a redirect. And this is where you use the router to direct them, where to go after they have logged in. So Cooking Sign-Up takes us to a redirect where we select the user. And then when we come back, the results is detected and we're back into the page. So our users are logged in, but this route is not protected using the angular fire off guard module. We can reroute any unauthorized user back to the log in page. The angular router has this concept of route activations, which means only allow someone to go to a routes if it meets certain set of criteria. Angular fire integrates with this with the angular fire off guard, which means only activate the route if the users logged in. And then we can further customize with the papabile methods like redirect unauthorized to. And using this method, we can say only allow users to get to the projects pays if they're locked in, otherwise send them back to the home. This customization is tacked onto the route in the data property. So now when I try to access this route, it kicks me right back to the log in page. All users in Firebase Off come back with a user I.D., which makes it easy to organize their data in the database. And we can get the logged in user with angular fire off as an observable. And this will come back lots of information. So using the magic of ARC's J.S., you can map over this user and only return back the information you need, such as the UI d. And a photo euro. And since this is an observable, you can map over it to create a new object such as this task which contains the user I.D. and their photo euro. And then afterwards, using tap, we can operate our side effect of saving the task. And as a side note, calling to promise. Make sure that the unsubscribed is called for you. Each task is saved with a eweida, which means that we can address the important topic of security. Now that we have authenticated users entering data, it's time to address security. Firebase is a platform that doesn't require you to run a server. So what keeps someone from accessing your data? Well, the answer to that is. I'm so proud of you. Security roles are their own language. They allow us to say who has access to what data and what that data should look like. There are a bit of a mix between access control and schemas. Right now, anyone can read or write to my database, which is bad. Security rules allow you to match at a path level with route like parameters. And then I can now match to the tasks and allow anyone to read or write. If the data they are trying to send in has a user I.D. property that matches the currently logged in user security rules has special variables that allow you to inspect the requests that's coming in, the data that's trying to be saved to database and be currently logged in user. And this allows you to be very specific with how you're going to secure your data. This current rule allows users to read and write data that they have created, but that doesn't really promote a collaborative environment. So let's create a role based system. Security rules allow you to write functions where I can look up data in the database using the built and get method which takes and a path to the data to read. So I will read at the projects and use a parameter for the project I.D. Look into the collaborator's sub collection and see if a user exists and what their role is. So now I can say if you own your data or if the role for the user is a admen or an editor, then they are allowed to collaborate in this project. So the current logged in user isn't an Admon or an editor, so they get immediately kicked out. So just for now, I'm going to manually add the user into the database as an editor. The I.D. will be there, user I.D. and we can give them the role as the editor. And when we go back, they're allowed to collaborate and edit. So let's add a feature that lets users add collaborators by entering an email address when the user enters an email address. You might think I know what I'll do. I will query the users and find them by their e-mail, get their I.D. and then just add them as a collaborator. And while that might work, it's not very secure because that means that either this user or everyone can read from your users collection, which probably isn't a good thing. So instead of doing that, we can create a collaborator request sub collection and we can request that someone with the proper security can add them as a collaborator. And it's a server where you would want to control that kind of access. And we can do that easily with cloud functions. All the work we've done so far is in the browser, but sometimes you got to run some server code club functions or Firebase allows you to run server code in response to firebase events. So you can send a push notification every time a document is created in virus store resize images that are uploaded to cloud storage. And just like we're about to do, read secure parts of your database. Let's build the cloud function. Cloud functions is all about triggered events, and for a store, we first specify a trigger with a document path which can contain parameters. The project idea and the e-mail in this case. And when a document is created, it will trigger this event. Firebase comes with an Adnen SDK that is specifically tailored to run on a server cloud. Functions contains all the environment variables you need so you don't have to hard code. Your configuration code functions is where you should write code that a client should not have access to. Like the ability to make a payment. So seeing your payment, private keys or having access to all of your users emails and other information, the admin SDK is very similar to the client SDK, especially API wise. So you can write queries just as you would with the client SDK. But since we're running in a node environment, we can take advantage of async. Oh wait, we don't need to stream this data in real time. We just need to get it once so we can query the users for their email and then just await the dot get method to get the data back and then return the first results from the query. Since we know there's only one user per e-mail cloud functions gives you context of every function in vacation and we can use that to get the parameters from the document path, such as the email and the project I.D. And we can use this information to securely add a collaborator by tapping into the project documents and going to its collaborators sub collection and adding that users I.D. and their role. One of the best practices for cloud functions is making sure that you return a promise from every trigger. This lets cloud functions know when your code is done so it doesn't have to run longer than it needs to. And we will return a promise of deleting the collaborator request so we know that they request has been fulfilled. What if this user is not in the database? Well, that means that they are not a part of the app. So we'll just do an EL statement for now and maybe, you know, work on an email server somewhere down the line. Now, when we add a collaborator by their email address, the cloud function triggers adds them securely. As an editor and the new user can modify tasks. Remember that to do comment about that e-mail server while I have about three minutes left in this video. So I think I can get it done. And that's because with the firebase extensions is a code less way of doing common tasks like resizing images and yes, triggering emails with extensions. I can set up a cloud function with just UI. So something that would have taken a lot of glue code can just be done in a few minutes. Oh yeah. I don't have time for a funny joke. Let's install the trigger email extension extensions. Do a lot behind the scenes. UI is designed to be transparent about the resources that are being created. The billing that needs to be enabled and the security access being granted to the extension extensions are configurable. And this is where you can tailor it to work for your use case. You supply your own S.A.G. server, the collection where you will trigger the email from and any templates that you want to use. It'll take a few minutes to install this extension. So let's look at the email templates in the database. Each document has an I.D. for the name of the template and a subject and the H.T. AML. And you can template this with handlebar style syntax. Back in the cloud function, lets trigger the email extension. This email extension actually works a lot like the cloud function that's written right here because it creates a cloud function trigger that listens to when documents are created at the mail collection. So when we add one that has a template name with some data, it will turn that into an email. So all we have to do is grab that data from the database that needs to be templated, which is the project and the admin user. And once we send a collaboration request, it will trigger this email if the user is not a user of the app. And it always feels good to remove it to do. Or we could just keep it there and confuse everyone. So let's add a user that doesn't belong to the app. And when they check their email, they get their invites, which contains the link that allows them to sign up for the app. I have like 30 seconds left. But that's plenty of time to get this app deployed on Firebase hosting to initialize Firebase will use the firebase JLI with Firebase in it. Hosting this will ask you what's your project name is, what's your public folder is and whether you want it as a single page app, which, yes, you do. This gives us our configuration in Firebase that Jason and our project list and Firebase RC. Then using the Firebase CLIA, we'll do Firebase deploy Desh nationally hosting to only to play hosting. And then we have our project, that web app. So I hope that was the best 20 minute angular and firebase video you will ever see today at Engy Cough in this timeslot, we covered a lot in those 20 minutes. So if you want to see a more in-depth explanation where it goes a little bit slower than tune in to my YouTube channel where I do live streams on firebase apps, and I'm going to actually be rebuilding this one. Starting next week. So thank you all so much for coming to my talk. And I hope you have a great energy, Compaq.