How to Create a Todo List with Phoenix LiveView (Updated for Phoenix 1.5)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi friends my name is dennis beatty a year and a half ago i published this tutorial to teach you how to create a real-time updating to-do list using phoenix live view as of now that tutorial has been viewed by over 6 000 people but a lot has changed with phoenix and live views since i first published it so parts of the tutorial no longer work this video is an update to that tutorial that should work with phoenix 1.5 and phoenix liveview 0.14 which are currently the latest versions of those libraries my twitter link is in the description below if you're watching this on youtube it's on the bottom of the post if you're watching this on my website let me know there or in the youtube comments if there's anything that you don't understand or that you want me to cover more in depth so phoenix live view is a great solution for anybody who wants to get a real-time app out to the world quickly without spending a ton of time building up both front end and back end today i just want to show you how simple it can be our to-do list will be backed by a database so you could use the same pattern for business applications to add real-time functionality without a ton of overhead since this is a tutorial for a bigger project i've pushed all the code to github if you are on the post on my blog you can click the github logo next to any of the section titles and it will take you to the corresponding commit so that you can check what you have against the full code base if you're watching this on youtube the link to the blog post will be in the description below so let's dive in to start out you'll want to set up a new project with phoenix live view thanks to the changes to the generator in phoenix 1.5 all the liveview boilerplate will be added for you when you generate a new project first make sure that you have the latest version of the generator if you run mix archive dot install hex phx underscore new this will try to install the latest phoenix new package from hex and currently the latest version is 1.5.6 so if you don't have that go ahead and use capital y to install that and with that installed we're ready to go now let's set up the boilerplate for our project so if you type mix phx dot new live view to do's and so that'll be the name of our application and then you can include this brand new live flag and what this will do is it will add all the boiler plate necessary to get live view up and running in your phoenix application so with that we'll hit enter and this will generate all the boilerplate files then we can fetch and install dependencies with capital y and so now i'm going to just use some movie magic and with a snap of my fingers all my dependencies will be installed it's going to take a little bit longer for you so feel free to pause the video and come back as soon as your stuff's installed and here we go with all of our boilerplate generated and our dependencies installed we can go ahead and move into the project directory so if you cd into live view to do's then i'm going to clear my terminal now we can set up our database using mix ecto.setup this will both create our database and run the migrations for it which right now there aren't any now you can start up your server using mix.phx.server and with that your application will be running before we go any further i'd like to take a second to plug my newsletter if you go to dennisbaity.com at the bottom of every page is a text box with a subscribe button next to them if you enter your email and subscribe to the newsletter you'll be one of the first to know every time i publish a new article about elixir about phoenix live view or about anything else so please take a second and subscribe if you haven't already with that said let's go to localhost port 4000 and you can see your brand new live view app up and running with your basic project up and running you're going to want to create a table to store the to-do list in since there's already plenty of great phoenix tutorials out there i'm going to skip over how to build your data schema manually so let's just use the phoenix generator to do that quickly so if you go back to your terminal and i'm gonna stop my server so if we run mix phx dot gen dot context to use to do and then we need to provide the table name to do's followed by the columns for that table so title will be a string and done will be a boolean and so let's generate that and that's going to create our migration it's going to create our schema and it's going to create our context along with tests for those so this is really everything that we need to do to get our data model up and running with that though let's migrate our database with mix ecto.migrate so now our database is all set up as well so we need to create an interface for interacting with the to-do list so i'm going to clear my terminal i always like to start from the top level when creating a page and then work my way down to the lowest level so in this case we're going to start at the router go ahead and open your editor and then open it to your router you'll find online 20 we have this route that says that we want to use the page live module go ahead and change page live to to do live and right now if you try to run your app you're going to see a compilation error because to do live doesn't exist yet so we're gonna go ahead and create a new file if you go into your lib folder then live view to do's web and then live let's here create a new file called to do live dot ex and go ahead and open that up here we're going to just create the boilerplate for a new live view module so if we say live view to do's web dot to do live then i'm not going to worry about module documentation now we're going to say use live view to do's web live view and this is a macro that phoenix 1.5 provides that will provide all of the necessary imports that we need for our live view to work properly now we will add our mount callback and that's going to take params a session and a socket and we want to return an okay tuple with the socket and we also want to provide a render callback and that's going to take in the assigns from our socket and then it's going to return just a simple string rendering live view you'll notice because we're using live view that we are going to use this lsigil which is the live eex template type that we need to return here so now if you save this file and go ahead and run your server again mix phoenix.server once that starts you can open your browser and you will see that you now have the text rendering live view on the page awesome so we've got that working but now let's actually do something with it so now we want to display the to-do list when the live view mounts we're going to want to load in the to-do list so that the live view can render it so let's go ahead and update our mount function if you stop your server and open up to do live when we use the generators to create our data model it generated a context for us so let's go ahead and alias that context with alias live view to do's dot to do's and then we're going to want to assign to our socket a list of to do's that comes from to do's list to do's and i can already tell that i'm going to get tired of saying the word to do's hopefully you're not getting as tired of it as i am so i'm going to go ahead and save this file now the live view process will have the list of to-do's but it isn't actually displaying them we're going to need to create a template file to do that if you go into lib then live view to do's web then live to the same place that our live view module already exists let's create a new file and we'll call this one to do live just like our live view module but this time we're going to say dot html.lex and go ahead and hit enter and so now we have this template file what we're going to want to do is create a for loop loop over each to do in our list of to-do's that we get from the assigns then we're going to create for each one of those a div that contains to do dot title and then we can end our loop so previously we would have also needed to create a view module and change our render callback to call the view and tell it to render the template but thanks to some new phoenix magic a template in the same folder as the live view module that has the same name will be used automatically so for a large project with many live views and templates this might not be the easiest way to organize things but because this project is smaller we're going to go ahead and take advantage of that so if we go into our live view module again we can remove our render function so that only the mount callback remains now i'm going to close my editor and start my server again you'll see that right now it's empty and that's because we don't currently have any to-do's in our database so let's make it possible to add new to-do's to the list to start we're going to want to add a new form to the top of our template so if you stop your server go into your template let's do this by creating a new form element we don't want it to have a normal action but we're going to give it this phx submit attribute and set that to add now this is going to instruct live view to send an ad action to the server that contains the contents of the form when it's submitted so let's close out our form now inside of the form we're going to want to add a text input and we'll call that input to do title and then let's give it the placeholder text what do you want to get done and then we'll go ahead and close that out then next to that we're going to want a submit button that will say add and we want to provide a special attribute called phx disable with [Applause] and we'll say adding now this is a nice light view feature that will disable the button when the form is submitted and change its text to adding so the user won't submit it more than once so if you were to try clicking that button right now nothing's going to happen in the browser and you're going to see an error in the console and so let me show you that if we type something simple and hit add it didn't seem to do anything and if we look here we can see that we have this error it specifically says this function to liveutusweb.todo live dot handle event three is undefined or private and that's because we haven't created that yet if we go back into our editor we're going to want to create a new handle event function that's watching for an ad event and then takes the to-do information that's passed in and creates it to do then you'll tell it to load the list of to-do's again so the list will be re-rendered so since you're already doing that in mount go ahead and refactor that into a private function called fetch so we'll say create a private function call it fetch we're going to take the socket and then we're going to assign to the socket to use is to do's dot list to do's and so now we can say that on mount we just want to say okay and fetch our socket now we need to actually implement our handle event function so if we say def handle event add and then we're expecting a to do to come in and that to do will come on the socket then we can say to do's dot create to do which is another function that came with our generated context and we'll pass in the parameters that we received from the socket and then we'll reply well actually we won't reply we will return no reply tuple and again we'll want to fetch the socket so that we get the latest to-do list items to be displayed to the user and so with that we can start up our server again now if you type a new title into the input and hit enter or click the add button you'll see that it shows up in the list below so this is great we can add new items to the list and it updates itself without us having to write any javascript let's take it a step further we can make it so that it will work across multiple sessions so that if you and i are both looking at the same to-do list you can add a new item and it will show up for both of us this is all going to be made possible by a library called phoenix pub sub phoenix live view is the star of the show in this tutorial but its older sister phoenix pub sub is doing a lot of the heavy lifting behind the scenes in case you haven't used phoenix pub sub before it allows you to set up subscriptions in your app to listen to topics and handle events when they occur since the process that manages the live view components won't necessarily be the same process that's updating the to-do list in the database we want to have the live view process subscribe to updates to the to-do's table phoenix pub sub comes bundled in phoenix by default so all you have to do is use it to start off let's go back to our editor and we're going to go to our context this time so this is the context that was generated for us we're going to want to add a function to enable subscribing we're going to want to use the module name as our pub sub topic if we create a new module attribute and we call it topic and we get the module name and we're going to inspect it and what this does is it takes the module name which is an atom and converts it to a string so that we can use it as our topic and then we're going to create a new function we'll just say def subscribe phoenix dot pub sub dot subscribe we want to subscribe to the live view to do's dot pub sub and we want to subscribe specifically to this live view to dos.to do's topic on that pub sub let's go ahead and save this file and go back into our live view now we're going to want to subscribe to the topic whenever our live view is mounted and so now with that process subscribed it's going to need to handle any events that come in so this can be implemented with a handle info callback and that's going to look something like this we say handle info and then we're going to receive a tuple that has to do's and then it's going to have a list that has to do and then something else after it and then there will be one other element in that tuple that we can kind of ignore right now and then we'll have our socket and so whenever this function is called by the pub sub we're going to want to send a no reply tuple and again we'll fetch our socket so what this is going to do is whenever a new to do is created or to do is updated phoenix pub sub is going to send a message to our live view process this handle info function will be called and it will then fetch the to-do's from the database and make sure that we have the latest to-do's so that then we can update our interface for our user so if we save this now that the live views are subscribed to the topic and handling events we need to actually broadcast events to them so if you go back to the context we'll create a new function called broadcast change and we'll send it an ok tuple with a result and then an event name here and we're going to want to then call phoenix.hubsub.broadcast and we're going to broadcast again on the live view to do's pub sub [Applause] and we want to broadcast to our topic and then we're going to send it the module this is coming from along with the event that's getting called and the result of that event then to make all of this work we're going to need to modify all the functions in the context that are going to mutate data in the database so that they'll call our new broadcast change function so the first one will be our create to do function so after insert we can call broadcast change and it's going to pass in the result of our insert which is going to be an ok tuple with our to do then we need to provide an event name and so we'll say to do created and so then we have our update to do function we can do the same thing and say broadcast change with the name to do updated and then we can go to our delete function here and we're going to need to change this a little bit but we can say to do and then repo dot delete and then broadcast change to do deleted and that's all there is to it let's go ahead and quit and start up our server again now if you open the app in a second window you can add new to-do's to the list and you'll see that they're being added in real time in both windows if we say goodbye you'll see that it showed up in both windows simultaneously even though i only entered it in the one so now anytime there's a change in the to-do's context it's going to be broadcasted out the live view processors are going to listen to those changes and then send the update down to the client in real time i don't know if there's ever been a way to build something like this with so little effort so now that you're properly creating and reading the list of to-do's let's give updating a shot since it's a to-do list you really got to be able to mark items as done right so to start off with let's go in and modify our template we want to modify our template to include a check box next to each to-do list item so that we can display whether or not it has been checked off so inside of our div here let's go ahead and add a check box and tell it that it should be connected to do done and the value should use to do dot done and currently we're displaying whether or not the to-do list item has been completed but we want the user to actually be able to check things off so let's add a couple more attributes to our check box if we add phoenix click and we'll call the event name toggle done then this will send a click event to our live view and then we can add phoenix value id is to do dot id and this will send the id of the to-do list item up to the live view event as well so that we know which to-do list item to mark is completed in the database if we save this file if we were to run this right now we'd get another error because we're not currently handling that event so let's go into our live view module and we're going to create a new function called handle event and again the event name is toggle done and then it's going to receive an id and so we want to take that and then it will also receive the socket and so we're going to want to get the to do item from the database and then we'll want to update that to do to set the done attribute to the opposite of what it is now then we will return a no reply tuple with our updated list of to-do list items there's an optimization that we can make here though whenever our to-do's context updates a to-do it's also going to broadcast to all of the pub sub subscriptions that that update occurred and so we're already going to be fetching the list of to do's so we can actually remove this here because it will already happen for us we can actually do the same thing here when we create a to-do if we run our server again if you try checking a few of the boxes you'll see that they update in real time even across multiple browser windows i don't know if i'm ever going to get tired of how cool that is and how easy it was for us to set up so there you have it we just created a simple to do list with phoenix live view it didn't take too long to implement like i said before live view is awesome and phoenix pub sub is pretty amazing too it was super simple to subscribe to events and publish those when you update the database and that allows you to get all this set up really easily i'd highly recommend spending some more time getting familiar with pub sub because it can be a very powerful tool in your arsenal as you build real-time applications if you want to keep going with this project the next thing i'd recommend is adding a delete functionality the to-do's context already has a delete to do function that you can make use of so you can probably use what you just did with the check box as a template if you do anything further please reach out to me on twitter let me know what you did i'd love to see the things you're building as a result of these tutorials if you like this please hit the like button below and subscribe to my channel so that you can get notified of my next videos i plan to continue releasing them with accompanying blog posts whenever i can make time i know i haven't been consistent in the past but i'm hoping to improve there let me know on twitter or in the comments for the video if there's anything further you'd like to see me cover but most of all thanks for watching [Music]
Info
Channel: Dennis Beatty
Views: 9,646
Rating: undefined out of 5
Keywords: elixir, phoenix, phoenix liveview, phoenix live view, liveview, live view, phoenix tutorial, liveview tutorial, live view tutorial, elixir tutorial, phoenix liveview tutorial, phoenix live view tutorial, programming tutorial, websocket, realtime tutorial
Id: xgz-HTot3R8
Channel Id: undefined
Length: 25min 59sec (1559 seconds)
Published: Mon Nov 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.