Dynamic New Form in Formsets with jQuery

A free video tutorial from Justin Mitchel
Coding Entrepreneur & Teacher - 568,000+ Students
Rating: 4.3 out of 5Instructor rating
37 courses
817,022 students
Dynamic New Form in Formsets with jQuery

Lecture description

Create new Forms in a Django formset by using jQuery

Learn more from the full course

Django Core | A Reference Guide to Core Django Concepts

Dive in deep to the core concepts behind the power Django framework written in Python. Using Django 1.10 with Python 3

24:12:33 of on-demand video • Updated April 2021

Django Models
Model Instance Methods & Properties
Model-level field validation
Django Forms and Formsets
Form validation
Model Form
Function Based Views (FBVs)
Class Based Views (CBVs)
CRUD in Django Views (Create Retrieve Update Delete List)
Django Templates
Django translation
Deploying Django on a Live Server| Heroku, Webfaction, Linode, Digital Ocean
Celery + Redis for asynchronous tasks and scheduled tasks
and much more!
Requirements are Python 2.7 or 3.3 and Django 1.8 & up
We use Python 3 and Django 1.10 in this one
English [Auto]
And this one, we are going to be dynamically adding forms to a form set view. That means that we will have a button much like the save and cancel button, but a button that says add new form and that will just add an actual new form for us so we can add new data. So we already start with an empty or one extra empty form. But what if we wanted to add like ten things before we actually save it? That's what we're going to be doing and it's going to be using a lot of jQuery. So we're actually going to skip the jQuery code. We will talk about it, but we're not going to go step by step with it. We will talk about each individual function itself. But the main thing here is to actually look at the code as it is now. You might be wondering why things look a little bit different. I just added some styling, so I added some bootstrap styling as well as this cancel button, which this cancel button really just goes back to the to the home page. It doesn't really cancel anything. It just, you know, changes the page. You could use it as a refresh button as well. That's essentially what it's doing without actually saving anything. It's just going to a new page so that a little bit of styling. And then I also added some new styles as well, using the template inheritance, of course. So block styles here. And then another thing that we added was the jQuery block here. And then we also added this jQuery color animation block as well. So all this code will be on GitHub. If you take a look at our GitHub for this particular project, you will actually be able to see all of this code as well, including this starting code. So we'll have something for this lecture to be the start code. So now we're going to jump back into our form set view and we are going to make some changes here. We're going to introduce this concept of an empty form inside of our form set. Now, of course, this is how your form is going to want to look, right? So we have our actual form set management form. We have form in form set, we have our Div class and we called it form row and then form ASP. Now of course, if you weren't doing forms and you wanted to use Django crispy forms, you can absolutely do that with crispy here. But we're going to stick with ASP just to not work with third party libraries just yet. So what we can do is we can actually create a empty form or render an empty form that has really no bearing on the actual form set. So let's actually take a look at that. I'm going to put it into a new Div class and I'm also going to give it as form dash row and then I'll give it an ID of empty dash row as well and we'll close off the div. Well actually before I do empty row, I'm going to leave that out and I'll explain why in just a moment. But we're going to come in here and do form set. So form set, dot empty form and as P so again, you can use crispy here instead of as P if you want, but we're going to leave it as P so as paragraph and we'll save this and we're going to render it back into Chrome. So going into Chrome, if we scroll to the bottom, we see two new forms here or two forms in general. And if I get rid of that empty form and save it refresh in here, we no longer see that form. We still see the row, but we don't see that extra form in there. So let's bring it back in and let's see what happens if I try to input something. So I'll say ABC or whatever on the actual form, or I'll put it on both of them and just kind of see which one stays. I hit save, scroll down. The validation error happens only on one and not the other, and that's what empty forms do is they actually don't have validation because it's really just an empty raw form. So we can do what we're about to do, and that is if we look into the inspect element, we can see this even further. Now, first of all, inside of the form, we're going to look at the code here a little bit is we have our form, our csrf middleware token. So that input is rendered from that template tag that we used. We have the button group a break, and then we also have the management form. So it shows us total forms, initial forms, minimum number of forms, maximum number of forms, and it has several different values here. Now the main value for us is of concern is the total forms one. So whatever that value is, that's what we actually want to look for. That's the most important part as far as this form is concerned. And right now it says four. If we count the forms, we got one, two, three, four, five. There's actually five forms, but the very last form, the empty form is ignored, right? So if we look at the empty form, like any of the inputs in there, by opening up all the little tags, I'm going to open up the ones on the other one. What we see here is we have ID form dash three dash user down here. We see in the empty form, we see ID underscore form, dash, underscore, underscore, prefix, underscore, underscore, dash, user. So it's quite different, right? So it actually is not giving us a number there and these numbers correlate the position that that form actually exists. So the fourth form is actually ID underscore form. Three. The very first form is going to be zero. It's going to show us zero. And it does. And that's true for each field, too. So what that means is we can use jQuery to copy this, change the actual prefix to a number of form or the next number of form. And then we can also change the total number of forms as well. So that's what we have to do. And we're going to do this in a few ways. So I'm going to close out the inspect just for a second, and we're going to come in here and I'm going to add the ID of empty form back excuse me, empty row. We save that and we don't have to resubmit the form. But what we see now is just that one extra form in there and then all the other ones. All right, cool. So now what I want to do is I'm going to copy and paste in this jQuery that we've already kind of created for you guys. So we're going to cut it out of our notes and paste it in here. Okay. So we're going to go line by line with this in just a second, but we want to add a few more things to our HTML and we're going to add a new button in here or a new href. And I'll just put the dollar sign there and I'm going to give this a button class of Add new form. So add new form is really going to be handling it for us and we'll say add new form and I'll put a plus sign in front of it and I'm going to put this down below as well and I'm going to call it BTN Link. So this is bootstrap stuff. You don't actually have to style it necessarily, but we're going to leave it like that. All right, so now we have this add new form button and now what we can do is use some jQuery to update it. So what we have here is we have this one says add empty lecture row. We're actually going to change that to being something different. We called it add new form. So I'm going to use that add new form class. There's a reason I'm showing you to do this is just so you check these things. If you ever copy and paste and use this code elsewhere. All right, so now we've got this add new form. So if I click on it, it will look for this empty row and then it'll do some stuff there and then we'll come through. So the first thing that you'll note is form ID equals two question mark. Question mark. So if I actually come back in here and inspect the element. Inside of the console. I get unexpected or uncaught syntax error. So this form ID has to do with well, hopefully you know what I'm talking about, but if you don't, we'll jump into the form again and it's the management form. So ID underscore forms, total forms. That is what we want to change it to. So I'm going to just come in here and change that into ID, underscore form total forms, and now everything else will actually update accordingly inside of this code. So what's happening here is when we click on this new form, it's going to look for that form ID. This might be different depending on what kind of form you're using or all types of things that might actually change. Even more reason to make note of it. Then we're going to copy the existing empty form. There's a reason we're copying it instead of just replacing it or changing it is. We want to keep that empty form in there. If we add 100 new forms. So then we're going to remove with our new empty row, we're going to remove the ID, so we're going to remove that original empty row because we made a copy and we don't want two of the same ID, especially not empty row because we have display on none there. And then we also want to get the total number of forms here. So we're passing the integer from the total number of forms. So we're getting this value and we're making sure it's an integer so we can use it in jQuery. Then we have this new form variable. We're just declaring that and then we're doing some stuff to the actual form itself, which we'll talk about in a second. But this actual form, it has to do with that empty row. And then after we do all that stuff, we append this to the very end. So the last row form, which if we scroll down a little bit, it's going to be after this empty form set, right? So it's going to be after the empty row itself as far as the HTML is concerned. But realistically, if you didn't have that class on there and you added it later, you would be able to just have it after that. Hopefully that's not too confusing. It might be, but that's something that you might need more practice with jQuery if it is finally what we want to do is update the form count to include the new row. So we're going to grab that original form ID So what we did up here and then we're going to update that new value to including the original total number of forms and then just adding one to it. And then finally, we're going to animate some stuff for that new form row. Okay. So the the next thing what we want to talk about is what's happening inside of the form. So we're updating the empty form IDs. So if I scroll up a little bit and I see this, this function for updating form IDs here, it's taking in an element and then it's looking for name of that element. So that current element name. So if we look at the rendered code inside of any given form, we're going to come in here and it's looking for a specific element for the name here. And as far as the name is concerned, we are going to want to replace that name. And then we're also going to eventually want to replace the ID, But notice the name itself and ID are not necessarily the same and the name is really the important one, not the other part. So with the empty form, if we look at that, the name again is has that prefix in there. So we want to change that prefix to follow the form numbers. So what we do here is we use some replacement code to get the total number of forms or whatever number is in there and then we can replace current name with that. So we take the original name, we look for this string of prefix right here, and then we do some substitution, change the the total number into that prefix and then we update the input accordingly. Now you see element, it is coming off of any of these inputs. So input, select or text area. So those are the ones that are actually being able to be changed. And then we set that input to those new names. So we remove the old names basically and put the new ones in there and then we create a new form row. So we're looking for the closest dot form row and that has to do with the empty form. So it's going to jump up and look for it. So in the rendered code, let's take a look here. We see that it's looking for this form row. So if you think about it, if we copied this this entire block here, let's say edit as HTML, basically what we're doing is we're copying this and we're pasting a new one and I'm getting rid of this, so I'm just simulating what we're doing in the jQuery itself. We're looking inside of each not label yet, but each name and we're changing it to being like five. So for each one, that's what we're doing. And what we do here is that's when we do this right? So we're changing the name and the ID, and then we look for the nearest row so we can change the we're going to add the same ID or a similar ID onto the row. We don't necessarily need to do those two things, but it is something that's nice to have. And then we're going to add this new class to that row. So a new parent class row, which we'll see once we do it. And then what we're going to do is grab the element's parent. Which is going to be whatever element it is. So in this case, the select element would grab the parent, which is P, and then it's going to change the label. So then we would want to change or excuse me, it's going to change the parent ID first and then it's going to change the label ID And again, we'll see this stuff in just a second. And then finally it will return the newly created row, which is what we append to the very end. Okay, So that's a lot of stuff going on and it's going to take some time. If you don't know jQuery that well to actually parse and understand all this information. But you might also have to rewatch what I just said. But again, playing around with this is something that you also might want to do. Okay. So now if we click add new form, notice what happens is it actually adds it. So if I click on Add new form, a lot of times it's going to add it through here. So it's adding another form, but it doesn't necessarily mean that it's going to validate those forms. So let's actually try it. So I'm going to hit Save and I scroll down and all those forms are still there, but there's nothing showing up, right? So it didn't actually try to save any sort of data. So there's no validation. So I do let's just add some more stuff in here and I'll just save those and that and then I'll hit save again. And now what we'll see is some validation errors showing up for all of that new stuff, right? And if we looked at the clean data, it would show that stuff as well. These extra form are still coming through and they're still there because when we go to our inspect element, our form now has a new value for total forms, right? So it's not it didn't change the value of total form. So when we submit it, it's still going to stick with that same value. And then as far as actually looking at the new forms, as we see here, all of these forms are coming through. So these are all these were all dynamically added, but then we submitted it. So let's actually add a few more dynamically added ones. And what we'll see is some changes is we now have these are all the dynamically added ones and it's giving us a form ID of 11, 12 and 13 and so on. So this is actually working. It's showing us exactly how we want it to be. The only challenge here is actually having too many extra forms, but that's where you could hit cancel and it would erase all of them. It's not really erasing them and it's not really canceling, it's just redirecting to a different page. But if we add a new form and say ABC again or whatever, hit save one more time and then we see that, you know, the slugs required, blah, blah, blah, and we say ABC one, two, three and then some other slug and we hit save. Now that data is in there, or at least it should be. So let's go ahead and refresh. And the data is brought to the top because because that's where we saved it and that's how it's actually showing up. So that new data is here. And then we have another empty form now at the bottom. And of course, when I click Add new form, it's it's doing a little animation. So that's what that animation is. It's scrolling to the top of that form element. So the actual row itself and then it is. So that's the animation scroll. And then it's animating a new background color because by default the background color is right here in the style. And then so that's it. That's dynamically adding new forms. With jQuery, again, it's a little bit of a complicated topic. That's why it's so long. If you have a lot of comments or questions about this, let us know because it might be worth actually doing more step by step jQuery specifically for this form set. Okay. Thanks for watching and we will see you in the next one.