- Read Tutorial
- Watch Guide Video
So with our current form, we are grabbing each one of the values, we're updating state, and you may think that we could perform the exact same process as we did with the login component. So if we open the login component, if you remember when we handled the submit, we posted to the API Endpoint, and then we created this client object, where we passed in the email and the password.
So your first natural thought may be that we can just mimic that, that we could simply say okay, this is gonna be our portfolio item object, and then we're gonna pass in the name, and the description and those kinds of things. That would work if you were working exclusively with text values and that is the key differentiator I want you to really focus on right here.
Because if you are working with text values, this is the standard approach for working with a form. However, we are gonna be working with images as well, and so in order to work with images, what we need to do is actually wrap those images up in a way that the API will be able to understand them. And the typical API is going to understand getting images in a form object kind of value, or should I say a form data value.
So what we're going to be doing now is going to be laying the groundwork for what we need in order to send all of that image data up to the server, because images are structured much differently than just regular text values, and that's because they're made up of all kinds of little bits and pixels and things that can't be wrapped up the same way that you would with regular text.
So, let's start building that out here, and I'm also gonna show you how you can access the values and make sure that they are working properly. So let's switch to Visual Studio Code, I'll close out the login, I'm also gonna close out these other files because we don't need them right now. And I'm gonna create a new method here and the method is going to have the single responsibility of building the form. So I'm just gonna call it that, I'm gonna call it buildForm
, it's not gonna take in any arguments.
The first thing you need to do is create the FormData Object. So I'm gonna say let FormData just like this and make sure that you have the F here in lowercase. And that is gonna be set equal to new FormData, spelled out exactly like this. And so what we're doing here is we're telling JavaScript I want to create a new FormData object and once we have this, we can add all of the other data points into it.
So the way that you do that is with a special function, and this is a function specifically built for FormData in JavaScript called append. So I can say FormData.append and then inside of here, this is gonna take two arguments. The first is going to be a string and it's going to be the string and structure that our API expects. That structure is going to be portfolio, underscore item, and then name, and name is gonna be in brackets, and then with a comma, 'cause we're making a second argument this.state.name.
portfolio-form.js
buildForm() { let formData = new FormData(); formData.append("portfolio_item[name]", this.state.name); }
So okay, that may look a little weird if you've never seen it before. The reason for this is because the API is going to expect an object, just like we saw with login, it's expecting an object such as client, with nested values for email and password, and that is the typical way an API works, it expects that kind of wrapped up values. Now here we need a way of representing that, and one way of representing an object and then calling those values is by using the bracket syntax.
So I will add the caveat that every API works slightly differently. So you're gonna have to rely on the documentation that you get whenever you're working with a different API, that this is a standard approach. The majority of APIs I work with have a structure similar to this. So what we're doing here is we're creating this FormData Object, then we are appending this value.
So when we created this, this is just an empty object, and then we're saying that I want to add this first element. It's going to have this kind of a key, and then it's gonna have a value of this.state.name. So that is how it's going to be structured and then we're gonna do it for the other items. So we're gonna say we also want to append the description, which is gonna grab the description from state, and we're gonna do that for each of the other values.
So form, append, and then this one instead of it being description it will be URL, and then we have the category and category.
buildForm() { let formData = new FormData(); formData.append("portfolio_item[name]", this.state.name); formData.append("portfolio_item[desccription]", this.state.desccription); formData.append("portfolio_item[url]", this.state.url); formData.append("portfolio_item[category]", this.state.category); }
Okay, so that's everything we need to do as far as appending it, now we need to return the full object. So what we did here was these append calls added to the FormData, and then from there what we need to do is have buildForm return that completed full object that will have all of these key-value pairs.
Now once we have that we need to call it. So inside of handle submit, I'm gonna get rid of this console log statement, and now I'm just going to call this.buildForm, and it's a function, so make sure you end it with parens, hit save, now nothing is going to happen that we're going to be able to see right here. So let's use the debugger to see exactly what is going on.
So I'm gonna add in the debugger, hit save, and now if I come into Google Chrome we'll just type in some values. And it doesn't matter whatever you type in here, this is just going to be a way of making sure that our form process is working. So now if I hit save, the debugger should be triggered, but it looks like it is not.
So let's see what issue we might have. So I do not see any errors here, so let's try it one more time, there we go. I forgot, for the debugger to work you're gonna wanna have the console actually already open. So that triggered, we have our debugger, now let's go into console.
And you may think because we have the debugger that we could just type in something like FormData, because we have that FormData Object and call it, and then you'd expect to be able to see each of those values we added. But FormData is actually a very special kind of module inside of JavaScript. It is loaded with all kinds of functions and so you need to call it a little differently than that.
If you open up the prototype which what this does is it is kind of the class definition, it shows you all of the functions you have access to. So we have append, which we already called, then we have delete, we have entries, we have forEach, get, getAll, has, we have all these kinds of elements. Now there's one that specifically is going to allow us to print out the values, and it is this value's type of function here.
So let me clear this and we're going to write a for loop to see all these values. So I'm gonna say for, var let's just say value of FormData.values, and it's a function so make sure you call it with one. And then inside of here let's just add a console log statement. So we'll say console log and print out the value, and then let's close this off, hit return, and here you go.
You can see each one of those items from exactly what I typed in the name inside of the description, the URL, and the category.
So we have each one of those items, and it looks like I did forget the position, but that's fine. The only reason we're doing this is to make sure that this part of it's working.
So hopefully that's making a little more sense. FormData is a special kind of class inside of JavaScript that allows us to wrap up our data in a way that servers are able to understand it for more complex data, that's a reason why it has all of those functions.
Now if that seems a little confusing, especially if you've never seen it for the first time, I have some good news for you. What we just walked through is actually more extensive than you're usually going to have to get into when it comes to FormData, when it comes to connecting this and passing this data to the API.
Literally all we're going to have to do is inside of our Axios call in handleSubmit, we literally just have to say this.buildForm, and it's gonna do the rest for us, it's gonna wrap up all the data, it's going to format the images in a way that the API is gonna understand 'em.
We don't have to do any loops or anything like that if we just pass in buildForm and the API takes care of the rest. But the first time I ever saw FormData, there's a little bit too much magic going on, and I don't like it when I don't understand the underlying concepts of something, so that's a reason why we took the time out to do that.
So let's get rid of the debugger statement here, and then let's also make sure we add in our position and the position value, and now we should be good to go. So if you come back here, hit refresh, everything should be working again.
But now instead of us manually having to call each one of those values inside of our Axios call, now we're simply going to be able to wrap it up in that nice FormData Object and then pass all of that to the API.