DEV Community

Samuel Lubliner
Samuel Lubliner

Posted on

Belay Board App Part 5: Add AJAX to Calendar

Right now all my actions use the redirect_back method. Now I want to be able to request, accept, and reject without redirecting or refreshing the entire page.

Improve this experience with Ajax

  • Change the default behavior of links and forms.
  • When the user clicks on a link/form, keep them where they are instead of sending them to a different URL.
  • Make the same GET/PATCH/POST/DELETE request as before, to the same route and with the same parameters; but it will be in the background, using JavaScript.
  • In the action triggered by the request, instead of responding with a .html.erb template or redirecting, respond with a .js.erb template containing some jQuery.
  • The jQuery will run in the user’s browser and update just the part of the page that needs it (sliding in the comment, updating the like count, etc).

At the bash prompt run these two commands to modify config/importmap.rb:

% ./bin/importmap pin @rails/ujs
% ./bin/importmap pin jquery
Enter fullscreen mode Exit fullscreen mode

Then in app/javascripts/application.js, I added these lines:

import "@hotwired/turbo-rails"
import "controllers"

import jquery from "jquery";
window.jQuery = jquery;
window.$ = jquery;
import Rails from "@rails/ujs"
Rails.start();
Enter fullscreen mode Exit fullscreen mode

Now change anywhere in the app that was using a Turbo-type request.

Change the link from submitting an HTML request to a JS request

Make it so that when the user clicks on the delete link, it doesn’t navigate them to the URL specified by the href="" attribute. Instead, keep them right where they are.

Attach a custom JavaScript event handler to the link that triggers the action so the appropriate CRUD occurs.

The request that is placed must be of the format .js, rather than .html. Then respond_to it accordingly.

The link_to and form_with methods accomplish all of this.

In the calendar

<!-- views/availabilities/index.html.erb -->

 <% availability.requests.pending.each do |request| %>

  <div id="request_<%= request.id %>" class="request-section">

    <p><%= request.sender.username %> wants to join</p>

      <%= form_with(model: request, url: accept_availability_request_path(request.availability, request), method: :post, local: false) do |form| %>
      <%= form.submit 'Accept', class: "btn btn-success btn-sm" %>
      <% end %>

      <%= form_with(model: request, url: reject_availability_request_path(request.availability, request), method: :post, local: false) do |form| %>
      <%= form.submit 'Reject', class: "btn btn-danger btn-sm" %>
  <% end %>
  </div>
 <% end %>
Enter fullscreen mode Exit fullscreen mode

Use jQuery to remove the comment from the DOM. Use a unique id="" or the helper method dom_id to easily select with $():

respond_to JS

Edit the accept and reject action to handle requests for format JS:

class RequestsController < ApplicationController
  before_action :set_request, only: %i[ show edit update destroy ]

  def accept
    @request = Request.find(params[:id])
    @request.accepted!

    respond_to do |format|
      format.html { redirect_to availability_requests_path(@request.availability), notice: 'Request accepted.' }
      format.js   # This will look for a file named `accept.js.erb` in `app/views/requests/`
    end
  end

  def reject
    @request = Request.find(params[:id])
    @request.rejected!

    respond_to do |format|
      format.html { redirect_to availability_requests_path(@request.availability), notice: 'Request rejected.' }
      format.js
    end
  end
  # ...
Enter fullscreen mode Exit fullscreen mode

Create template files

// views/requests/accept.js.erb

console.log("accepted");

$("#request_<%= @request.id %>").fadeOut("slow", function() { $(this).remove(); });
Enter fullscreen mode Exit fullscreen mode
// views/requests/reject.js.erb

console.log("rejected");

$("#request_<%= @request.id %>").fadeOut("slow", function() { $(this).remove(); });
Enter fullscreen mode Exit fullscreen mode

Next Steps

Now that AJAX is working for accept and reject, I will add AJAX to the other buttons on the calendar.

Top comments (1)

Collapse
 
heratyian profile image
Ian

Wow!