Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails change boolean value with checkbox and jquery ajax

I am new to rails and trying to change the value of a boolean via a checkbox and using jquery ajax:

<%- @tasks.each do |task| %>
  <div class="task-wrapper">
    <%= check_box_tag 'completed', task.id , task.completed, :class => "task-check" %>
    <%= content_tag :span, task.task %>
    <%= content_tag :span, task.deadline %>
  </div>
<% end %>

and the javascript:

$(".task-check").bind('change', function(){
  if (this.checked){
    var bool = this.checked ? 1 : 0;
    $.ajax({
      url: '/todos/toggle',
      type: 'POST',
      data: '{"task_id":"'+ this.value +'", "bool":"'+ bool +'"}'
    });
  }
  else {
    alert("no");
  }
});

then the controller:

def toggle(task_id, bool)
  @task = Todo.find_by_id(task_id)

  if @task != nil?
    @task.update_attributes(:completed => bool)
  else
    set_flash "Error, please try again"
  end
end

finally the routes:

resources :todos do
  member do
    post 'toggle'
  end
end

also tried collection but gives the same error.

when ever i try it i get a 404 error on the action.

what is the problem?

thanks

like image 873
Wahtever Avatar asked Mar 22 '13 14:03

Wahtever


2 Answers

As of Rails 4, there's a way to do this without needing any additional JS or CSS:

<%= check_box_tag 'completed', task.id, task.completed,
      data: {
        remote: true,
        url: url_for(action: :toggle, id: task.id),
        method: "POST"
      } %>

It turns out that adding remote: true to an input causes jquery-ujs to make it ajax-y in all the nice ways. Thoughtbot's "A Tour of Rails jQuery UJS" briefly touches this (and many other good things available); the "Unobtrusive scripting support for jQuery" page in the jQuery UJS wiki does a thorough job on this as well.

like image 111
Jim Meyer Avatar answered Nov 12 '22 11:11

Jim Meyer


Try the following (leaving everything else as is):

the javascript:

$(".task-check").bind('change', function(){
  if (this.checked){
    $.ajax({
      url: '/todos/'+this.value+'/toggle',
      type: 'POST',
      data: {"completed": this.checked}
    });
  }
  else {
     alert("no");
  }
});

the controller:

def toggle
  @task = Todo.find(params[:id])

  if @task.update_attributes(:completed => params[:completed])
    # ... update successful
  else
    # ... update failed
  end
end

Take a look at bundle exec rake routes to show you the paths that rails generates. In the case of your post 'toggle' which is a member you get a path like /todos/:id/toggle, hence the updated url in the ajax.

In the controller the :id from the path ends up in params[:id]. The data from the ajax request also ends up in the params hash, hence params[:completed].

like image 24
ramblex Avatar answered Nov 12 '22 11:11

ramblex