Okay, so this episode should be called something like 'extending the users plugin', but I'm not going to do that. I'm going to do something that I have spent a few hours trying to do, and that is Ajax form validation. In the next episode is going to be extending our users plugin, but I just want to show you this first because we already did the contact form, we did sending emails, we did the validation, but that validation wasn't by Ajax. It actually refreshed your page and then displayed the errors.
What we want to do now is display the errors, but we don't want to refresh the page. So the mail is sent by Ajax and the page doesn't refresh, but the validation refreshes the page if the user does some wrong inputs. So in this episode, we are going to be doing that. And I'm doing this because I spent a few hours trying to figure it out. Actually, I thought it was going to be very simple, and it is once you know what you're doing. So it's going to be simple for you, but it wasn't simple for me. I spent at least three hours trying to figure that out. So in this episode, we are doing the Ajax form validation.
Demonstrating the Current Page-Reload Problem
So this is the way our contact form works right now. If I do something like this in here and click send, we get validation messages, but as you can see, the input fields clear. And that is not something we want, because in this example, that is not a problem. But if you had a form with twenty fields and the user screws up one field, all of the fields would be cleared and the user wouldn't be very happy with that. So we are going to do these error messages via Ajax.
The October CMS Ajax Framework
And to do that, we are going to be using the Ajax framework that comes with October. You call the Ajax framework, we already called it, and you should always actually call it when you're doing October, but you call it in your layout file. So layouts/default in your theme, and you call it via this tag, so framework extras. Also, you can delete the extras, but the extras give you some extra options, actually not options, but features. So when I click send, you see this blue line, so that's the extras part. If you don't want that, you can remove the extras, but I would suggest that you leave it as it is.
Refactoring the Backend for Ajax
So, this is the Ajax framework. You can read about it. I'm not going to go into details how it works. You can read about it on this page, but I've had a little trouble with this documentation because most of the examples right here are for making a calculator, which you will need like never. So I don't know why the documentation is written that way, but you have some helpful hints here and there and with those hints I was able to create Ajax validation for our form. So we are going to do that right now.
So in whichlearn/components/contactform, actually watchlearn/contact/components/contactform, we have this HTM file, and we have contactform.php. In that contactform.php, we validate our inputs, and then if the validator fails, we return a redirect back. So this is the refreshing part of our page with errors. And we do validator. And now on our default.htm file, which is displaying our contact form, we display those errors via these tags. So for error in errors, and then we just display all the errors that we have on our page.
Implementing Ajax Partial Rendering
Okay, so the first thing we need to do, we need to get rid of this redirect right here. And instead of that, we are going to return an array. We are actually going to render a partial. That's how the Ajax framework works. It renders a partial that doesn't need a page reload to work, and it displays some HTML, JavaScript, or whatever you want. So to do that, you just do this:
return ['#result' => $this->renderPartial('contactform::messages', [
'error_messages' => $validator->messages()->all()
])];
So what we said right here, find the result div, so the div with the ID of result, and then render a partial in it. And that partial is going to be in our contact form right here, we are going to make it. And that partial is going to be called messages. And then when you render that partial, you can send some data to that partial. In our case, we are going to call that data or that variable or an array. So we are sending the array of messages, we are going to call it error_messages and that should be it. So we are sending all of the error messages to our partial. Okay, I'm going to save this now and then we'll make that partial.
So the partial is going to be called messages.htm and you put it in the contactform directory or folder. Okay. Now in here, we are going to set up the display of our error messages, but before we do that, I just realized I screwed up a little bit of code right here. So this should be like this. Okay, so now this is okay. We just save it.
Creating the Error Display Partial
And then we go to our messages.htm. And since we are passing messages right here to that partial, we can just do something like this:
{% for message in error_messages %}
<p>{{ message }}</p>
{% endfor %}
So we are just using a for each loop to display all the messages in our error_messages array. Okay, and now this of course doesn't work yet because if we go right here, refresh the page... of course I have a syntax error. And it's probably something to do with the semicolons like I do always. So the line 38, yeah, okay. Now, if I send it, nothing actually happens.
Connecting the Frontend and Backend
The page didn't reload, we didn't get error messages, and nothing happens. Why? Because we have to go to our default.htm. And if you remembered, we said we want to display the messages in the div that has an ID of result. So I'm just going to go below the form and create that result div. Okay, save it. And also, right here, onSend, you would do contactForm::onSend, so that October knows that this onSend method is actually connected or it is in the contactForm component. Okay, save it.
Testing the Ajax Validation and Identifying a New Problem
And let's see if this works right now. So if I click send... Okay, let me refresh the page first actually. Okay, let's try to do it now. And as you can see, we get the name field is required, the email field is required. And if I do something in here, so I just enter a name and click send again, now only the email field is required. Basically, as you can see, the value that the user has input right here stays right here, so the user can change it. The same thing would be for email and for the messages.
Now, if you remember in the previous example, so when we didn't have Ajax validation, when we click send, we would get the messages right here also, so below the fields. And also, we could put CSS on our input fields and maybe make it a reddish color or something like that to notify the user that those are the fields that have something wrong inputted in them.
Inspecting the Error Data Structure with JavaScript
Okay, so to do that, there is maybe a better way, I didn't find a better way, so I would appreciate if someone with a bit more experience in October can help me out with this. But this is the way I've found how you can do the same thing right here. So remember, we are rendering a partial when sending our Ajax request and when we are getting those errors, and that partial is right here, so below the form. So we don't have a way to put those messages right here. But of course, I found a way to do that.
So we would go to messages and we would do script. And let's first of all see what we are actually getting from those error messages, because we are going to need to change it, change it up a bit because we will need some more information. But let's see for now what we are actually getting out right here. So I'm just going to create a variable called errors.
So this right here is the important part. So you can with Twig, you get those error messages and you can display it in your console, but you have to encode it with JSON. So you do json_encode and do raw. So that's very important. Don't do it without this because then you are going to get a screwed up response. So we're just going to console.log this out. Okay.
Modifying the Backend to Return Field-Specific Errors
Let's go to our page, open up our console right here, and let's just send this. So as you can see, we just get 'The email field is required.' What we actually want, we want to get the name of the field first of all. So the name of the field for name is going to be name. The name of the field for email is going to be email. So we can check it out right here. So the name is name and here the name is email. And we want to say with JavaScript, okay, go to the input that has a name of name and below that input, display this message right here. But as you can see, we are not getting the name of our input field.
And to do that, we are going to go to contact form right here and we are going to copy this out. And we are not going to call these error_messages, we are going to call this field_messages. And then the validator is going to return validator->messages(), but not all, it's just going to return validator->messages(). Okay, save this. And if we go to our messages.htm and we're just going to rename this to field, save it, refresh the page. And now if I click send, let's see what we get. So we get an object. As you can see, we get the name of the message and we get the message itself. So the name in this case is email, so 'The email field is required', and the name in this case is name, and 'The name field is required'. So we are now getting that object right here and we can do stuff with that object, pretty cool stuff actually.
Using JavaScript to Position Error Messages
We can go through it with the each function for jQuery, and we can say, okay, take the name and then apply that, apply some message, so the message that we are getting right here, apply it below this input field.
So what we are saying right here is go through all of these errors and make variables called i and object. So the object is going to be the message itself and the i is going to be the name of our field and then we are saying with jQuery so create a div with a class of error-messages and add that object in it. So the object, actually let's just call it as it is. So I'm going to call this name and I'm going to call this one message. Okay, so name and message.
So this is the message right here. We are going to add that to our div, and the name, we are going to use the name to say with jQuery, under which field do we want to display that message? So we're just going to do insertAfter and then find with jQuery the input that we are looking for. Okay, and that should be it.
So we are telling jQuery, create this div and put it below the input that has a name of name, so either email or name right here. So let's just see if this works. I'm going to refresh the page and click send. And as you can see, we are now getting this, 'The name field is required', 'The email field is required'.
You can also do something like finding that name and adding a class of has-error or something like that, and then you can with CSS in some way highlight that field that has a wrong input in it. Also, what you would need to do right here, because if I go right here and click send again, as you can see, these messages are now duplicate. So what you would do before anything happens, you would just clear those error messages. So you would do something like, so before this triggers, find error-messages—that's why I gave it a class of error-message—find error-message and remove it. So remove all the error messages that exists right now and then put it up again depending on what we are getting in this errors array. So let's just try it out. If I click send right now, as you can see, we are now just getting one error message, and that should be it. So that's the Ajax validation for you. As you can see, it is not complicated at all, but it took some time to get to this place.
Conclusion and Next Steps
Okay, so this is it for this video. Remember everything we did here will be available for you on GitHub, the link will be in the description below. You can ask me questions on Facebook or on Twitter or on the comment form below this video, either on my site or on YouTube. And of course, if you like this video, please give it a thumbs up. If you like the channel, maybe, I don't know, subscribe to it. And that's it for this video. Thank you, guys, for watching and I will see you in the next episode when we will be talking about extending our users plugin.