 Can you all get started with us on it? This is my talk about the Drupal Ajax framework. My name is James Hall. I work for CTI Digital up in sunny Manchester. Let's get started then. Here are some of the topics that I'm going to be running through in my talk. First of all, we think you should use the Drupal Ajax framework. Some of the benefits of it. I'm going to look at a new review of some of the broader concepts behind the framework and how it works. I'm going to start looking at how you can use full API to set up Ajax requests and then alter parts of the form without a full page refresh. We also have a full API where we look at some other ways to trigger an Ajax request. Then you're an important graceful declaration. What happens when JavaScript is switched off and how the framework supports that? Then the concept of Drupal Ajax commands, what they are, what they do and how we can use them. Then some of the new cool stuff in Drupal 8. We'll find out some questions if anyone has got any. I'm basically going to be running through a number of different examples starting off basic and then progressing through the presentation to get a little bit more advanced. For each example, I'm going to have a little animated gif to show you what the output is to the user. Then we'll go through a couple of code examples. There's going to be a Drupal certain example and a Drupal 8 one. We'll spend a bit of time looking at the differences we've got to look out for when you're migrating from 7 to 8. On to why I think you should use Drupal Ajax. I don't think I need to sell Ajax to anyone here. It is pretty cool. Also, if you use the framework, you can have Ajax with no JavaScript. I like JavaScript as much as the next developer, but it's pretty cool because you don't need to write a single line of JavaScript to Ajax enable your applications. Graceful declaration comes as a feature of the framework, which is pretty cool. As long as you do things right, you'll get that for free. It's extensible, so if it's not something in core that you want to do, then the chances are you'll be able to extend it to satisfy your requirements. It's reusable. You can patch it up into your modules, use it on other projects or contribute it back to the community. Finally, if anyone is familiar with Drupal behaviors and you've extended Drupal behaviors to write your JavaScript in your Drupal projects, then this integrates with Drupal, the Ajax framework. Essentially, if your behavior that attaches something to an event on a particular element within the page, if there's an Ajax request that replaces that element, ordinarily you would lose the event handler but because of the integration between Drupal behaviors and the Ajax framework, it will attach again for you straight away and you don't need to do anything. Here's my own view of what's going on. You stand on the left and you've got the client browser on the right-hand side. You use something within the API to generate what the docs refers to as a trigger. This could be a form element or just a link. That will then get sent to the client. Most part it will get sent via the Drupal settings variables. That's received by the Drupal Ajax library, which is the Ajax.js. It will take these instructions, which are basically saying, take this element and make it trigger an Ajax request. When it triggers an Ajax request, it will go to a particular endpoint on the server and it will be asking for some instructions as to what to do. The call wrap will say, right, we've received this request, do something on the page. That will either be, for example, set some CSS on an element or replace some content within a certain wrapper. Most commands go back to the Ajax.js, interprets those commands, and then it carries out the action for you. It might seem pretty abstract, so let's move on to some examples. Here's my first example. Pretty amazing. You can see what's going on. One is selecting from a drop-down. The page is getting updated with the number that is selected. As you can see by the little loading icon, there's no page refresh going on there, so that's all being done over XHR. What's going on behind the scenes there? You probably should have said this before. You do need some familiarity with FormAPI to sort of these examples to make much sense, but at the top, we have the call back, mostly standard FormAPI stuff. You've got your title, type select, and then you've got the option of one, two, and three. The key bit here is the hash Ajax key on that array. In this example, we're specifying three options. The only one that's actually mandatory is the first one, but we'll come to why that is later on. We've got the call back, which is for Drupal 7, it's ordinarily just a string name of your function. We've also got the feedback wrapper. The feedback wrapper relates to the ID of an element on your page. Also, we've got the method, which is append. As you saw from the example, every time someone clicked on the drop-down, you'd see a new thing added to the element, so you've selected a number, whatever. If I didn't add method append, the first time that request went over, it would just replace the wrapper, and there'd be nothing to replace the next time someone selected something. By default, the method is replaced, so it's worth bearing in mind. Below that, we've actually got the markup, which will be used to wrap the content that comes back from the server. It's within that, the feedback wrapper that you've selected, number X. The call back relates to PHP function. Obviously, below that, that's where it's passed the form, and that will contain the values that have just been selected by the user. I'm checking to see if the number element has got any input. If it has, I'm taking the number, and I'm constructing a string, a new selected number, and returning that. The important thing to note here is that in Drupal 7, you can just return a string, and that's absolutely fine. In Drupal 8, things are a little bit different. Probably the main difference really is that you're probably going to have your Ajax callback within a class, so you'll need to provide a fully qualified signature for the callback. On this one, we've got a reference to a static. The most important thing is that the function needs to be static, I believe. I think that's right. We might have to check that one, but anyway. The callback function is pretty much the same thing going on, apart from using the new call form state interface to get values stuff to get values. Next example. This is a sort of dependent dropdown thing going on. The first one is someone selecting a category, animal, mineral, and vegetable. The second dropdown is then altered with options that relate to the first category. Pretty standard stuff. What's going on here is more typical of a sort of example of how people will implement logic to alter the form that's returned to the user. Instead of having logic in the callback, what you'll see is the actual logic is in the form builder callback. We've got a category at the top. That's the thing that's triggering the Ajax request, so it's got the Ajax, the hash Ajax key. Like before, it's got the callback and the wrapper. The wrapper will come soon in a second. The effect on this one is another option that you can pass along, which is completely optional, which is fade. That relates to how a jQuery will replace the effect it will use when it replaces the content on the page. In this example, you can quite tell that it will fade into view. We're grabbing a category from the form state values. The second dropdown, it's getting its options from this utility function here, which I've not included. Basically, it takes a category and it will generate a list of options that relate to that category that you've given it. Most importantly, this element is then wrapped by a div with the idea of selection method, which is the same idea that you've given to the Ajax key for the previous element. In the callback, there's really hardly anything going on. Before the callback gets called, the form has been rebuilt. When you make the Ajax request, the form gets rebuilt. Once you've made the Ajax request and there's some input in the top select, it's already changed the select time for you. In the Ajax callback, you don't need to do anything, because by the time it gets there, the element's already been modified and it contains the updated list of options. This is typical of what you see. You could have implemented the logic in the callback, but it's more difficult to find it in the form builder. You can see that it's pretty much the same, really, with the exception of the callback. Next example, we're going to come on to a little bit about the great school degradation here. We've got a form, a really simple form, one element that takes the first name and a submit bone. The first time we try to submit it, we get a standard form of your validation error. It says this field is required. On submitting the form, you get a nice little message saying thank you. All this is taken place without any page refresh, and the messages are getting repended to the form. What's going on here is that the... I've only got a duplicate example for this. The submit bone has got the Ajax option on it, and it's saying replace the page... The areas on the page to replace with the content return from the callback is the personal details wrapper, and as you can see at the top, the whole form is being wrapped by a div with the personal details wrapper. The callback is just returning the entire form, so that means that we've got a wrapper of the entire form, and then when it goes to the callback, it's just checking the entire form back. Validate is the standard validate stuff, and on the submit, we've got a message set. The important thing to notice here is that we haven't had to do anything special with the messages or the validation messages. The Ajax framework will just send them back for you and prepend it to the wrapper. That means that when you return it, the personal details wrapper will first have the messages inserted, and then it will have to form. The reason this is quite cool for this whole process of the validation callback being called and the submit callback being called for you is that if I just switch Ajax off on this form, it just works. There's nothing you have to do. The people with JS-enabled browsers form just works as I was saying, but it's just delivered by a full HG request. The framework does help us in ways to take place in other ways, but that's one. It's some more interesting stuff. What's going on here? We've got a username, like a sort of mock-logging form. You enter your username, and as we're tabbing out of that field, it's automatically printing out a validation message to say whether or not that username is valid. Probably not a very realistic example, but it's good just to demonstrate some stuff. There's two times there are a lot of usernames going in, and we're putting a red border on the username field and we're just printing a little message below just to say that's an incorrect username. There's a couple of different things going on there. I do seven. I think I've not included a password field there yet, so we've just got the username field, got the callback, the event is blur, so it's probably worth noting that, by default, Dupal will trigger the request on change, so for most things, that's fine. When you change a select list, it will change when you change the value, when you set a radio, or for buttons, the default method will be clicked, so it usually just works with that for you. The text input is not really so great to have it on change because it will send a request every time you key up in the field. It makes more sense as a fly-off to AJAX request when the user taps out or loses focus on the field. Following the field, we've just got an empty div, which is user AJAX feedback. The callback, what we're doing is we're checking, we're getting the input from the username field. We've got a little utility function which I've left out, but I'll go back and check to see if the username is valid. If it is valid, we're setting the border color to red, no green, sorry, a long way around. If it's invalid, we're setting it to red, and we're setting a message to see if your username is not valid. If it is valid, we're setting up a message string of nothing, and the border color is green. Instead of returning a string like we have done in the previous three or seven examples, what we're doing is we're setting up an array of instructions to send back to the browser. We're pretty self-explanatory. The first one we've got is the AJAX command CSS. This is kind of a wrapper for the jQuery AJAX method. The first option that it takes is an ID, and then the second is an array of key-value pairs for CSS properties. In this one we're saying find the element on the page with the edit user ID, and then set the border color to either red or green. Finally, we're adding another command which is html command, and we're just sending a string back to that. What that's going to do is it's going to replace the inner html from that div. The return value from this command is very specific. You need to pass it an array, and it's got this type is AJAX, and then the array of commands that we've just constructed. AJAX will iterate through each of those commands and then carry them out, as you saw before. It will change the border color for you, and it will insert the message into that div. It's a bit of a change. There are a couple of things here to notice. The return value from the call batch, instead of returning an array now, we now return an AJAX response object. To send some commands back, we use the add command method on the object, and the add command method takes AJAX command objects. Other than that, it's the same principle, really. You're still passing along an ID, and you're still passing an array of CSS properties, and then you just return that response. One thing we're looking at here is that the html command in this example is taking a render array rather than a string, so that's a new feature in Jupylate. You can use render arrays instead. The other thing worth pointing out here is this disabled refocusing on the texting part. I'm not sure if it's a bug or not, but in Jupylate, when the AJAX response comes back to the browser, if it's a text field, it will try to refocus the element that triggered the request in the first place. The offshoot of this is that you type into... If you've got it on Blur, you type into that text field, tab out. As soon as it comes back to the response, you get refocused back into your text field. If you try to tab out again, it does exactly the same thing. It's impossible to leave the text field, basically. You can actually pass these to the disabled refocusing to True. Can I ask a question about the... Absolutely. You've got the commands at the bottom, so one is essentially to update the CSS, and the other one is to turn the HTML. Is it possible to apply a class, so your CSS may be to find a red border, so could you say apply a class on this element of error? Is that another kind of... We'll go through a couple of the commands later on, but for that one, I don't think there's a specific command for adding classes to elements, but... Can you extend it to do... You can actually extend it, or there's a catchall useful command called invoke, which is like a wrapper for jQuery, basically. So invoke will take, and we've got a couple examples later on, but invoke will take any jQuery method and an array of the argument that you expect, so you could just pass that class to that and then pass the id, and that'll do the same thing. For the most part, you don't need to actually do any extending. So invoke works a lot of time. So this is probably the most boring screen recording in the whole world. So we've now come to look at other ways. So perhaps an error just looks at how you can use form API to set up triggers, but now looking at how you could use something outside of form API. Most of the examples you see would be a link, so each time you click on this link, there's a dip below getting updated with a number. Pretty groundbreaking stuff. This other example is... What happens when JavaScript isn't enabled? So the user's still seeing something, basically. It's not quite as cool, but it's not breaking completely. So let's just have a look how you set that up. So we'll first look at the middle function. So that's my page callback. That's what's printing the links onto the page. The first thing you'll see now is we're adding a library to the page. This is really important when you're not using form API because when you're using form API, it will take care of a lot of stuff for you, so it'll add the library to the page. If you're circumventing that for whatever reason, you need to make sure it's on the page. Otherwise, Ajax.js just isn't there to do its thing. The link, hopefully you can see it all yet. So we're going to... We've got a link at href. It's caused wellness to the page callback that we've got above. With the all-important, nojs within the link. I'll come to why that's used for the second. The class is useAjax. That is a special class. Ajax.js will... When it's loaded on the page, it will go through your markup and look for any links that has the useAjax class on it. If it finds one, it will... ...overwrite, prevent the default method, which is redirected into another page, and it will do an XHR request to your endpoint that's in the href. Following that, we've just got the wrapper, which is Ajax result. What the hell is that thing below it? That's the link. That's the link. The callback is pretty Mickey Mouse stuff. We're just generating a random number. Within the command, we're saying we've got the content, which is the number inside of the diff. Another thing when you're outside of full API, you can't just return that array. You need to return it using Ajax Deliver, which will set the correct response headers and return it as a JSON response rather than trying to return it as HTML. What is Node.js doing then? If you look in the menu, the hook menu implementation, you can see that it takes a parameter of the third position, and it passes that as an argument to the callback. For default, it will be passing Node.js as an argument to our callback. When Ajax.js is ran on the page, it will look for any links that use Ajax, and it will replace Node.js with Ajax. This is a really cool way of knowing when you're responding to a request, trying to figure out whether or not it's come from a JavaScript-enabled browser or not. Based on the information that's passed us, we can then differ our response. You can see in the callback that we've got their logic, and now it is Ajax, then we're returning with Ajax Deliver, and if it's not, we're just returning a standard renderer aid, and it's just rendered as HTML. That's pretty cool. I think that's a pretty nice feature for free. It certainly takes a lot of work out of it, and I think it's best practice to be making sure our app is gracefully degraded. Ajax links. This is the D8 example. Obviously, the root information, how we define roots in Jupylate is completely different. Same principles. Same thing going on with the link. I suppose the biggest difference here is that in Jupylate, you have to use the attached property on your renderer aid to get a library on the page. Other than that, in the callback, it's the same thing going on. Here are some of the other commands, basically. There's a whole heap of commands that come in call. In Jupy7, the easiest way to find them is just to have a search for your code base. What do they start with? Ajax commands. The ones that come in call are all prepended Ajax commands. In Jupylate, the easiest way to do it if you've got PHP Storm is to find the interface, which is the Ajax commands interface, and if PHP Storm can tell you all the classes to implement that interface. There's a whole heap in that Jupylate. It's got some new call ones. The ones that are in both 708, we've got a whole lot of content commands and so it depends, etc. CSS stuff. Adding CSS to an inline element, or you can add it globally into the page. A thing I mentioned earlier, which is invoke, which is pretty powerful, because you can pretty much call anything in Jupy or using that. The one you probably don't ever want to use, really, which is the alert command. In DA, they've adopted some of the commands that used to be provided by Ctools. We've got a way of redirecting browser to the Ajax response. I'll be honest, I actually know what that does. Sounds cool, right? It scrolls off, I'm sure you can imagine what that does. Probably the one that I'm most excited about, which is the Modals and Dialog command. These, some parts of jQuery UI are now in call, and we've got the jQuery Dialog, which is a big improvement, I think, on the Ctools Dialog. It looks a lot nicer, and obviously it's maintained elsewhere. It's cool, so it's going to look quickly how much time I've got. John, am I right for a bit? Cool. This is an example of how you can really quickly use Modals to do cool stuff, call-ish stuff in this example, but hopefully you'll see the potential. Two links on the page. I've got the Modalized Node 1, which I think I've just clicked. That was the node and the comments form at the bottom, and we've also got to create a new page node. Probably the only thing we want to point out here is that obviously it's just the content from the page. On the first example you see the save and preview, and actually the comments, the buttons that come with the comment form. On the node form you've got save, published, unpublished, and preview. That's the action buttons that you get on the node, edit, add form. I'm not sure whether it's a good thing, or not, but it will actually move those buttons into the footer for you. Sometimes I think it might be what you want. It looks nice. I'll just show you how easy it is to get that up and running. These really do play examples. The first one we've got, a random array is spitting out two things which are our two links. The first one I've just shown you a couple of ways of doing it. We've got a link, and it's linking to the node slash one URL. I've got to use the new way of links, take a URL object. The way to get this working in the Modal is that the link should have at least the two attributes, which is the class of useAJAX, and then the case of dialogue type of modal. The third one, which is optional, which is a number of arguments that you can pass to jQuery dialogue objects. In this case, you say, make it 400 pixels high and 700 wide. One thing of this point out in the example is what the difference... It wasn't particularly obvious to me. Originally, what the difference in dialogue and modal was, in jQuery is actually just an option on the dialogue. So you can say make this dialogue and modal in jQuery. You can see there's two separate things. Essentially, the first one has a complete full-page overlay. So that's the modal. Correct. The second one that doesn't have a grayed-out overlay is a dialogue. That first render array is essentially spitting out the marker that you can see below. In the second one, we're just returning a render array of just constructing the marker ourselves. We can see all the attributes that I've just mentioned. Obviously, it's easier to use JSON encoded and those quotes should be HTML encoded as well. The only difference between the first and the second one other than the HRF is that we're setting a different dialogue type of dialogue or modal. Finally, we've got to attach the library. You can see it's pretty quick to start using modals. They might not be that useful. In that first example, when you click on the save button, it will redirect you to the no-view pages it does normally. But it's easy to and it passes the wrapper format as a query which basically when Drupal responds, it will only give you the content region. It takes care of that a lot for you which is really cool. Slightly more advanced example then. So, it actually misses the point where I've got an empty input for the employee name, but since you've got the first text field typing name in there, hit the find employee button and it will give me a list of employees. Click on one of those employees and it will automatically insert the 10 minutes, insert their first name, surname and department into there for you. Not really a real example, but you know, you get the idea. So this is kind of using a couple of the things that we've touched on so far. There's a bit of code where it's at. So the first, we've got the form. We've got the employee name. Just standard text field. Nothing funny going on there. And then on there, we've got a button directly below it and it's all the stuff we've seen before with the exception of the limit validations key. This is important if you're using an Ajax request, sorry, if you're using a button to fire off an Ajax request, then you need to make sure that it's not really caring about some required fields below. So if I didn't put that on there, it's going to come back with loads of messages saying you need to put some values into these fields. So that's just basically telling form API we're not trying to submit the form and just doing something else. And yeah, the first thing I've admitted the other fields. So in the callback, what's going on, so we're setting up an Ajax response and we're using a utility function to get a list of employees that match that name. So that's coming back with an unordered list of employees that you saw with links in there. We're attaching the I'm not unsure what's going on here. I had to manually attach the dialogue library for this to work. I think when you're doing it with links it will do that for you, but in this example I had to explicitly ask for the library to be included. And then instead of the form we're working, it's magic, I've had to so when the button's pressed the response is coming back saying open them up, open a modal and put this content in it and make it 600 pixels wide. So you put the name and the click on button comes back. List of links of matching names in the modal for you. So because that utility function you can see that it's just taking the name it's finding employees from another function it's rating over the results and generating a list of links. These links have got the use.ajax class and we're passing the employee ID as a parameter to this root. OK, I'm returning that. So how you're following still. So that root is defined here and what the hell, yeah. So each of these links is hitting up this root and that root is then going on in this callback. So open the modal it's got a list of links, click on that link it's making yet another Ajax request that Ajax request is falling into here it's using this utility function to get the full details of the employee from that we're then sending back loaded command saying, and this is the invoke command saying use the jQueryVal method to set the value of the first name, last name department to the things that have been returned from our API. And then finally we're passing along and close my modal dialogue command. So that's what's going on there. Any questions about that one? It's a little bit more going on there. When you set the width of the modal you just passed in a number but you said that it was in pixels here. Does that mean you can't pass in any other unit? You know what? I'll have to have a look at the jQuery UI docs I think. Maybe. It's strange that it takes a unit list I would assume that it only takes... It's rubbish, yeah. Yeah, it can be worth looking at. Maybe it just takes pixels by default. Maybe if you pass a unit it will override that, not too sure. Right. My time up. Five minutes, cool. Right, last two seconds then. Thanks for sticking with me. So extending the format it's actually really, really simple. So those use those functions that we saw earlier on the AJAX command. This is taken from call. This is the alert command. It just returns an array just says what the command is which is alert and then anything following that will be the parameters that pass to the command for you. So in Dupal 7 you don't have to use these helper functions to return those arrays obviously. You will do because it's easier but you could just pass the array if you like. Now that matches up to the AJAX AJAX.js will be looking for a method that extends wait for it, Drupal AJAX the prototype.command So if it finds alert an object that extends a class that will method that extends commands with that name then it will pass it will instantiate that function and that's where our logic is. So you can see here it's just simply opening alert. The parameters that we pass so the text parameter will be properties of the response object that gets passed to that. So you can just see it's text and we're not passing title. Drupal 8 a little bit more long-winded obviously. So the class has to extend command interface and by doing that you have to implement render. But render is just returning the same array. So it's still pretty simple. And differences on the JavaScript side so instead of the structure is changed a little so instead of AJAX prototype commands it's now Drupal AJAX commands which I think sounds more proper but I'm not really sure. I think that's me. Any questions? Go for it, yeah. D8 specifically because of all the there's a lot of jQuery dependent looking stuff going on in there. And how easy it is and possibly encouraged these days it is to disable jQuery especially if you want to. Does this just fall apart if you do that or is there a... Absolutely. I mean it's slightly coupled with jQuery unfortunately. And I do think really one of the downsides of using AJAX frameworks is just to force you into weird ways of working because you're not really writing any JavaScript you're forced to do all your logic on the server which sometimes is inefficient to do it on the server better to do it on the front end. Are there any siloed parts of that AJAX framework that could work without jQuery as long as you know which bits do depend on which bits don't so you can still go over from the server? So I mean in theory you could you can use whatever you want in your custom command as up to you but the actual requests will be delivered using unless obviously you can override parts of the framework so I suppose I don't know what it is exactly AJAX.request maybe you can override that and slot in something else I suppose so you could override it maybe globally after I'm looking at it so good question though mate. So in D7 you've got the examples module which includes a lot of full API stuff and it includes some AJAX you've got the same in D8 Anyone know? Yeah Well a lot of this stuff will just be what I've just gone through today is find good examples in that On the question about formalization you showed the example when you changed the focus to another text element in the background that was a AJAX code You showed an error message but I didn't see the example where you changed the state of the form to whether it's valid or not So that was just time to form API stuff so if you can find that So the error message is so the color but I don't see what's happening when you're actually solving the form So people are submitting the form the first time I go through this I didn't provide it There it is One minute So you submit the form without a value in that field and that just comes back with a validation message I'm not having to because that's standard form API stuff because I've got a requirement Oh right sorry mate Right Yes whether it's valid or not but what would happen if you actually do you have to implement the validation twice one in the callback one in the form's actual validation or there's a practice That's a very good point yet So it would be better practice to have had that logic in a validation callback and then on form state there's a method to form get errors I suppose So you could have checked to see if there was some validation flagged against that field So yeah it would have been better for graceful decoration it would have been better to have moved that logic into the validation callback for sure Cool I think that