Update Field on Click from view

I simply want to have a checkbox that updates the todo.status = 1 onclick and then returns to the index view.

<% @todos.each do |todo| %>
    Checkbox here <%= todo.details %> 
<% end %>

1 answer

  • answered 2018-01-13 17:32 Sebastian Palma

    I think you could start by adding a check_box_tag to the view, where you're rendering all of your todos. Since that checkbox won't be attached to any form, then check_box_tag will be used insted the check_box helper. It'll contain a data-id attribute which will be the todo id value, important to identify which Todo specifically update:

    <% @todos.each do |todo| %>
      <%= check_box_tag 'check', todo.status, false, data: { id: todo.id } %>
    <% end %>

    Then you can check whenever the checkbox has been marked as checked and create a request, which will be processed by a method in the controller, and update the form status, like:

      let checkbox = document.getElementById('check')
      checkbox.onclick = function() {
        if (checkbox.checked === true) {
          let xhr = new XMLHttpRequest()
          xhr.open('POST', '/update_todo_status', true)
          xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
          xhr.onreadystatechange = function() {        
            if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
              window.location = JSON.parse(xhr.response).url
          xhr.send('id=' + this.dataset.id)

    There you get the specific checkbox, add an onclick listener, and whenever the user checks it, then it creates a POST request by setting the content type and specifying the todo id.

    Then in your controller you create the method:

    skip_before_action :verify_authenticity_token, only: :update_todo_status
    def update_todo_status
      todo = Todo.find(params[:id])
      todo.assign_attributes(status: !todo.status)
      render json: { url: todos_path } if todo.save

    Note you need to add the skip_before_action callback, to tell Rails not perform a CSRF protection when doing the request. In addition, in the method, find the specific Todo with the id provided, assign the attribute status by "flipping" the current status value, and then render a json containing the url where to redirect, just in case the todo modification has been saved/updated.

    Then just create a POST route pointing to the created method in the controller:

    post '/update_todo_status', to: 'todos#update_todo_status'

    Maybe you'll want to add the onclick listener to all checkboxes in that view, you can do it by getting all those elements, iterating over them and adding the listener.

    Maybe you'll also need something to do when the todo hasn't been updated, you can just add an else clause to the if.