Welcome back.
This is such a cool example, isn't it?
Let's go to our index file.
And here we are.
We've literally got a very, very simple index file.
We've got no action attribute on the form because remember, we're going to be using AJAX.
We've coded up our server side file that's going to give us error messages or success messages depending
on whether the form is valid or not.
So how do we type AJAX?
How does it work?
What do we do?
Well, it is JavaScript, right?
AJAX stands for Asynchronous JavaScript and XML and we know all JavaScript has to be included within
script tags.
The first thing I want to do is I want to grab our form and inputs.
That's the first thing I want to do. I just want to grab them and put them in variables
so if we need them later, we can use them.
So for example, let's grab our form, let's access our document, querySelector()
and we want to grab our form.
There we go.
We've literally got our form. And we can also grab our inputs, right?
We can grab our username input, do the same thing, document,
but this time, let me just mix things up.
Let me say getElementById(),
remember we gave it an ID of ...
ID of name.
The reason we can't use, by the way, querySelector() is that only selects one element.
And as you can see, we've got two input elements.
That's why I didn't access the querySelector(), I accessed getElementById().
We can do exactly the same thing now for the food input.
We can access our document object. On here, getElementById() and we gave it an ID of food.
If I scroll up,
I know I'm going slow, but you need to stay with me here because we're going to get more complex soon.
We gave it an ID of food.
So there we go.
We've got both of our input elements, but I also want to grab our wrappers, our two div wrappers.
Let's grab the one called divName. That we can just document.getElementById(), and we gave it an ID
of usernameWrapper.
You can do exactly the same thing, but now we can say divFood,
document.getElementById() and ID we gave
it was foodWrapper.
And I think that's it for now.
I mean, if I've missed something, we can always, always grab it later.
So how do we kick everything off?
Well, we need to listen for an event.
I only want to start executing code
when the user clicks on this, "Send my details" button.
In other words, when the submit event has been fired on the form.
So in order to listen for the submit event on the form, we grab our form variable, we then add an
event listener.
The event we want to listen for is the submit event.
And then of course we want to execute our callback, right?
And just to show you it's working, we can console log
"hi".
Here we go.
Let's access the console.
And let's just click submit and we get "hi".
So we know it's working.
But you'll notice every time the user clicks on submit, we get a browser refresh.
And I don't want that to happen.
We've done this before as well,
but when you use the addEventListener() method, we get given a object, specifically the event object.
Usually it's common practice to put it in a variable called "e".
We could call it anything we want.
And on this event object we've got a method called preventDefault().
It's basically going to prevent the default behavior of the browser, and that is, it's going to prevent
the browser from doing its refresh.
In fact, it's going to prevent the browser from even sending the data to a server.
So if we just refresh now and now the user clicks submit, we don't get a refresh.
In fact, we don't even get things appended to the URL. Let me just make it very clear,
there is data in each of the input elements, user clicks submit, but nothing happens.
This is brilliant because we are now in complete control as to what happens next. What should happen
next?
Well, the next thing I want to do is I want to grab all of our form data.
And we could start doing it ourselves.
But I want to use the FormData API given to us by the web.
In other words, I want to define our form data in a variable called formData
and I want to access a web API called FormData.
The FormData is a constructor that just creates a new form data object.
When we use it, that object is going to be populated with the form's current key:values using
the name property of each element for the keys and their submitted value for the values.
And it's super easy to use.
We just use a "new" keyword because it is a constructor and of course we access this FormData,
you can see my IDE already tells you what it is.
We can use it easily with an AJAX request.
And of course it takes one argument and the one argument it takes is our entire form.
So that's all our form data in this variable.
And like I mentioned, we're doing this because we're going to be using AJAX, and the object we're
using in AJAX is going to require this form data object when we submit it to the server.
Let me just write a comment here.
Grabbing our form data.
Now what I want to do is, for the first time, I want to set up our AJAX query.
They are a few different ways to set up an AJAX query.
We could use the new Fetch API but don't want to do that.
I want to just show you the old-school way of setting up an XMLHttpRequest object.
The reason I want you to know that way is because once you know that way, the Fetch API is going to
be super easy for you.
Okay, so I'm going to be using the XHR object.
Let me show you what I mean.
The first thing I want to do, though, before I set up AJAX is I want to define two things.
I want to define the URL, aka, where are we going to send the form data to?
And I want to define its method.
Is it POST, is it DELETE, is it PUT, is it UPDATE, etc etc.
So let's define a variable called URL.
Let's submit it to the same directory we are in, right, but the php-server-file.php.
So that's where we're going to send our form data to.
It's almost equivalent if we were on our form element here and we had the action attribute, it's the
same thing, but we just putting it now into an AJAX request in a URL.
Then let's define its method as POST.
It could have easily just have been GET, but I decided to use POST. And now we can actually set up our AJAX.
Let's put our AJAX query in a variable called XHR. In order to set up an AJAX query, we accessing the
XMLHttpRequest constructor, so we have to use the new keyword.
We access this XMLHttpRequest() constructor function.
That's nothing we've defined - that's provided to us straight out of the box by the browser.
So there we go.
We've got our XHR object.
Now in order to open and send an AJAX request, we have to first open the request.
We then have to define what happens on a successful response and then we have to actually send the request
to the server.
So let's deal now with opening up our AJAX request.
This is step one.
Remember these 3 steps, right?
Opening up our AJAX request is step 1. To open it up, we access our xhr object, and on here there's a method
called open().
And you can see it takes two arguments at least.
The first is the method.
And we've already defined the method in a variable called method.
We've defined our URL in a variable called URL.
And then the last argument we can give this open method is whether we want it to be asynchronous or
synchronous.
We want it to be asynchronous so we can just pass a value of true.
Very, very simple.
But we've literally opened up our AJAX request.
Step two is define what happens on a successful response.
Again, there are many ways to do things when it comes to coding.
How do I want to now define what happens on a successful response?
Well, something you need to bear in mind is that there's an "onreadystatechange" property that's fired through
the whole process.
You know, when AJAX makes a call to the server, there's an event fired.
When the server receives it, there's an event fired ... through the whole chain.
Eventually, when it comes back, another event is fired.
So what I'm saying is I'm going to be listening for the onreadystatechange, but I'm only really
care about when the readyState is 4. And when the readyState is 4,
it basically just means the AJAX call has been successful and we have received a response.
And I'm going to be listening for when the status is 200, so when everything has been successfully
completed, in other words.
So let's do that.
Like I mentioned, all I want to do is I want to access our AJAX object.
I then want to listen for the "onreadystatechange" events that are fired consistently and every time
it's fired, we're going to implement a function and execute a function.
But we only really care about the one state.
And the one state is if this XHR object has a readyState of 4 because we know then it's all complete
and I want its status to be 200 because now in this block of code we know that everything has been successfully
completed.
We know we've got the response.
So this is kind of where the meat happens.
This is where all the interesting stuff happens. In our server file,
if we scroll to the bottom, we know that we've given back the browser this data in JSON format.
So when we grab it, I actually want to convert it into a JavaScript object, a nice object that we
can work with.
So let's define a variable called response.
We are going to access this JSON object.
This is given to us by the browser.
It has a method called parse(), and we want to pass in the actual response. And to access the actual response,
we grab our AJAX XHR object and on here there's a property called response.
(sneeze. Oh, excuse me).
So there we go.
We've got our response.
And then what do we want to do with this response?
Well, let's define the success case.
If the response
is in a success state.
Now, remember, we have the success property on our response, right?
If we go here in our response, aka in that data array,
we've got a property called success.
And if it's in a successful state, we know it's going to be true.
So in other words, we're going to say, if this is true, what do we want to happen?
Well, very, very easy.
We want to access our entire form and change its innerHTML and assign it the value of the message property.
Because if we go to our PHP file, we've given our response, our data, a message property and that
is our success message.
And maybe I should stop here.
Yeah, well, you know what I'm going to do?
Let me say,
failure case.
Okay, but I'm not going to code anything yet.
What I want to do is I want to send this and let's just test our code.
Let's don't go too far before we test.
In other words, I want to send our AJAX request.
So outside here, I want to do step 3, send our AJAX request.
And this is very, very simple.
All we have to do is access our AJAX XHR object and of course, access the send() method.
And remember, we defined all our form data in the formData variable.
Remember?
That's why we did it.
So what are we sending to the PHP file?
We are sending the formData.
Let's save this.
Now, in order to for this to work, we need a server running.
If we go to the browser now, let's just go to the console.
If the user types something and click send, it's not going to work.
Go to the console.
We've got a 405 error - method not allowed.
In fact, if we go to the Network tab and hit our post request, our server is not running, so nothing will happen.
But what's really cool is we've got this formData, right?
So we already know that the form data is being sent in the body correctly.
It's just the case that this PHP server file is not found.
So why don't we go here,
let's kill this current server, which is what I've done, right?
And let's start our own server.
So let's open up the terminal. And all you have to do is once you've got PHP installed on your device,
you can start up your own PHP server on a localhost.
All you do is you write the keyword PHP, dash capital S for server, and then we can tell our server
on which port to listen to.
Here I want to listen to port localhost:8000.
We do this and we're done.
So now what we can do is we can go to our browser type localhost:8000 and here we go.
Here's our form.
We literally listening
to our form here.
Let's go to the console.
Clear everything. If we now
type in a value in each field and click submit,
what do you think will happen?
Unexpected token.
That shouldn't happen.
All right.
There's an unexpected curly bracket.
Oh, you know why?
PHP is very, very picky.
We have to end each statement with a semicolon.
Silly me.
So here we go.
Here we go.
Else, there should be one here.
This looks fine.
Let's save this.
Right, let's refresh this.
Say the user types in each box
so we shouldn't get errors.
Click submit.
And there's our success message.
How awesome is that?
So there we go.
It's all working.
And what's really, really cool is that it's all coming from this, right?
Cool.
Okay. Now I want to deal with this failure case.