Last active
January 28, 2020 04:32
-
-
Save eliotsykes/75ae13dbe4b9f6718f4f to your computer and use it in GitHub Desktop.
JSON API with jQuery AJAX and Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Wrap in anonymous function to avoid adding variables to global scope needlessly. | |
(function($) { // $ is jQuery | |
function addTodoToDOM(data) { // 'data' is object built from response JSON | |
// id will be needed when adding delete functionality dynamically. | |
// var todoId = data.todo.id; | |
// Add HTML for new todo to document | |
var tableRow = '<tr><td>' + data.todo.description + '</td></tr>'; | |
var todosTable = $("#todos"); | |
todosTable.append(tableRow); | |
todosTable.show(); | |
}; | |
function clearForm() { | |
// Clear input field | |
var descriptionInput = $("#todo_description"); | |
descriptionInput.val(""); | |
}; | |
function handleError(error) { | |
// Relies on error response from API being JSON object like: | |
// { errors: [ "Error message", "Another error message" ] } | |
var errorsObj = $.parseJSON(error.responseText) | |
var errorMessages = errorsObj.errors; | |
alert("There was an error: " + errorMessages); | |
}; | |
// Not needed for HTTP Basic Auth | |
function getAuthToken() { | |
// meta tag in <head> holds auth token | |
// <meta name="auth-token" content="TOKEN GOES HERE"> | |
var authToken = $("meta[name=auth-token]").attr("content"); | |
return authToken; | |
}; | |
// LEFT AS REMINDER, NOT needed if using HTTP Basic authentication! | |
// | |
// The browser will take care of gathering credentials for HTTP Basic Auth | |
// as long as authenticate_or_request_with_http_basic is being used for authentication. | |
// | |
// authenticate_or_request_with_http_basic will send a 401 Unauthorized with a | |
// WWW-Authenticate response header which trigger the browser to prompt for username | |
// and password using native dialog. This username+password will then be cached | |
// by the browser and submitted correctly as an Authorization request header tagged | |
// on to all AJAX requests to the server. | |
// | |
// function getHttpBasicAuth() { | |
// var encodedCredentials = window.btoa(unescape(encodeURIComponent(getUsername() + ':' + getPassword()))); | |
// return 'Basic ' + encodedCredentials; | |
// } | |
function createTodo(event) { | |
// Prevent click from triggering form submission default behaviour | |
event.preventDefault(); | |
var descriptionInput = $("#todo_description"); | |
var description = descriptionInput.val(); | |
var todo = { "todo" : { "description": description } }; | |
var ajaxOptions = { | |
type: "POST", // HTTP verb, one of: POST, DELETE, PATCH, PUT, GET | |
headers: { "Authorization": getAuthToken() }, // Not needed for HTTP Basic Auth | |
url: "/api/v1/todos", | |
dataType: "json", | |
contentType: "application/json; charset=utf-8", | |
data: JSON.stringify(todo) | |
}; | |
// Initiate the AJAX request | |
// Docs: http://api.jquery.com/jQuery.ajax/ | |
$.ajax(ajaxOptions).done([addTodoToDom, clearForm]).fail(handleError); | |
}; | |
function deleteTodo(event) { | |
event.preventDefault(); | |
// Get the delete button that was clicked (event.target) and | |
// wrap it in a jQuery object. | |
var clickedElement = $(event.target); | |
// The delete button needs a data-todo-id attribute, e.g. | |
// <button data-todo-id="7" data-delete-todo-button="true">Delete</button> | |
var todoId = clickedElement.data("todo-id"); | |
var ajaxOptions = { | |
type: "DELETE", | |
headers: { "Authorization": getAuthToken() }, // Not needed for HTTP Basic Auth | |
url: "/api/v1/todos/" + todoId, | |
dataType: "json", | |
contentType: "application/json; charset=utf-8" | |
}; | |
function removeTodoFromDOM() { | |
// Assumes that the delete button is a child element of the | |
// todo's table row. | |
var todoRow = clickedElement.closest("tr"); | |
todoRow.remove(); | |
}; | |
$.ajax(ajaxOptions).done(removeTodoFromDOM).fail(handleError); | |
}; | |
function setupTodoHandlers() { | |
$(document).on("click", "[data-create-todo-button]", createTodo); | |
// <%= button_to "Delete", delete_todo_path(todo), | |
// method: :delete, data: { :"delete-todo-button" => true, :"todo-id" => todo.id } %> | |
$(document).on("click", "[data-delete-todo-button]", deleteTodo); | |
}; | |
setupTodoHandlers(); | |
})(jQuery); // IIFE (Immediately Invoked Function Expression) | |
// Pass in jQuery to prevent other code from changing what $ means to this code above. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment