**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON https://guides.rubyonrails.org.** Working with JavaScript in Rails ================================ This guide covers the built-in Ajax/JavaScript functionality of Rails (and more); it will enable you to create rich and dynamic Ajax applications with ease! After reading this guide, you will know: * The basics of Ajax. * Unobtrusive JavaScript. * How Rails' built-in helpers assist you. * How to handle Ajax on the server side. * The Turbolinks gem. * How to include your Cross-Site Request Forgery token in request headers ------------------------------------------------------------------------------- An Introduction to Ajax ------------------------ In order to understand Ajax, you must first understand what a web browser does normally. When you type `http://localhost:3000` into your browser's address bar and hit 'Go', the browser (your 'client') makes a request to the server. It parses the response, then fetches all associated assets, like JavaScript files, stylesheets and images. It then assembles the page. If you click a link, it does the same process: fetch the page, fetch the assets, put it all together, show you the results. This is called the 'request response cycle'. JavaScript can also make requests to the server, and parse the response. It also has the ability to update information on the page. Combining these two powers, a JavaScript writer can make a web page that can update just parts of itself, without needing to get the full page data from the server. This is a powerful technique that we call Ajax. As an example, here's some JavaScript code that makes an Ajax request: ```js fetch("/test") .then((data) => data.text()) .then((html) => { const results = document.querySelector("#results"); results.insertAdjacentHTML("beforeend", data); }); ``` This code fetches data from "/test", and then appends the result to the element with an id of `results`. Rails provides quite a bit of built-in support for building web pages with this technique. You rarely have to write this code yourself. The rest of this guide will show you how Rails can help you write websites in this way, but it's all built on top of this fairly simple technique. Unobtrusive JavaScript ---------------------- Rails uses a technique called "Unobtrusive JavaScript" to handle attaching JavaScript to the DOM. This is generally considered to be a best-practice within the frontend community, but you may occasionally read tutorials that demonstrate other ways. Here's the simplest way to write JavaScript. You may see it referred to as 'inline JavaScript': ```html Paint it red ``` When clicked, the link background will become red. Here's the problem: what happens when we have lots of JavaScript we want to execute on a click? ```html Paint it green ``` Awkward, right? We could pull the function definition out of the click handler, and turn it a function: ```js window.paintIt = function(event, backgroundColor, textColor) { event.preventDefault(); event.target.style.backgroundColor = backgroundColor; if (textColor) { event.target.style.color = textColor; } } ``` And then on our page: ```html Paint it red ``` That's a little bit better, but what about multiple links that have the same effect? ```html Paint it red Paint it green Paint it blue ``` Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*` attribute to our link, and then bind a handler to the click event of every link that has that attribute: ```js function paintIt(element, backgroundColor, textColor) { element.style.backgroundColor = backgroundColor; if (textColor) { element.style.color = textColor; } } window.addEventListener("load", () => { const links = document.querySelectorAll( "a[data-background-color]" ); links.forEach((element) => { element.addEventListener("click", (event) => { event.preventDefault(); const {backgroundColor, textColor} = element.dataset; paintIt(element, backgroundColor, textColor); }); }); }); ``` ```html Paint it red Paint it green Paint it blue ``` We call this 'unobtrusive' JavaScript because we're no longer mixing our JavaScript into our HTML. We've properly separated our concerns, making future change easy. We can easily add behavior to any link by adding the data attribute. We can run all of our JavaScript through a minimizer and concatenator. We can serve our entire JavaScript bundle on every page, which means that it'll get downloaded on the first page load and then be cached on every page after that. Lots of little benefits really add up. Built-in Helpers ---------------- ### Remote Elements Rails provides a bunch of view helper methods written in Ruby to assist you in generating HTML. Sometimes, you want to add a little Ajax to those elements, and Rails has got your back in those cases. Because of Unobtrusive JavaScript, the Rails "Ajax helpers" are actually in two parts: the JavaScript half and the Ruby half. Unless you have disabled the Asset Pipeline, [rails-ujs](https://github.com/rails/rails/tree/master/actionview/app/assets/javascripts) provides the JavaScript half, and the regular Ruby view helpers add appropriate tags to your DOM. You can read below about the different events that are fired dealing with remote elements inside your application. #### form_with [`form_with`](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with) is a helper that assists with writing forms. By default, `form_with` assumes that your form will be using Ajax. You can opt out of this behavior by passing the `:local` option to `form_with`. ```erb <%= form_with(model: @article, id: "new-article") do |form| %> ... <% end %> ``` This will generate the following HTML: ```html
``` Note the `data-remote="true"`. Now, the form will be submitted by Ajax rather than by the browser's normal submit mechanism. You probably don't want to just sit there with a filled out ` ``` Since it's just a `