开发者

Rails3 Update Boolean Checkbox from Index View

开发者 https://www.devze.com 2023-03-19 18:47 出处:网络
I\'m building a simple tasks application for our company as part of an ordering system. I have a list of tasks with a number of rules. Nothing complex... What I\'m stuck on is the addition of a check

I'm building a simple tasks application for our company as part of an ordering system.

I have a list of tasks with a number of rules. Nothing complex... What I'm stuck on is the addition of a checkbox to complete the task. I want it done live, from the index view without having to hit submit..

Am really not sure even where to look. I figure I need to use ajax to do this - can anyone recommend a tutorial or tell me what I should be looking for.

Have also thought about a plugin, like the edit in place ones out there.

Thanks in advance

--- EDIT 1 --

Following advice from @pcg79 below, I've added the following to my application but am not understanding how I go out actually changing the status.

In my index view I have this:

<%= check_box_tag 'complete_task_1', '', false, { 'data-href' => tasks_path(@task) } %><

I've added the following to my application.js (added a # to get it to call properly)

 $('#complete_task_1').click(function() {
  $.ajax({
    url: $(this).data('href'),
    type: 'PUT',
    dataType: 'html',
    success: function(data, textStatus, jqXHR) {
      // Do something here like set a flash msg
    }
  });
});

For lack of understanding, I added this to my tasks controller:

def completed 
    @task = Task.find(params[:id])
    @task.status = true
 end

Which seemed reasonable but wasn't sure how to actually call that in the ajax?

In my development log I can see it sort of working but it says this:

ActionController::RoutingError (No route matches "/tasks"):

-- EDIT 2 --

As per advice from @jdc below, I've tried adding the following to routes.rb:

get 'tasks/:id/completed' => 'tasks#completed', :as => :completed_task

But still get the RoutingError.

-- Slight Update --

Following the excellent advise from @pcg79 below, I've updated my files with the following.

Routes.rb

get 'task/:id' => 'tasks#completed', :as => :completed_task

Index.html.erb

<td><%= check_box_tag 'complete_task_1', '', false, { 'data-href' => completed_task_path(:id => task.id) } %></td>

Tasks controller

def completed 
    @task = Task.find(params[:id])
    @task.status = true
    @task.save
  end

I get no errors in my browser, but my development log shows this:

ActionController::RoutingError (No route matches "/tasks"):

For a simple checkbox, this is hard work!!!

-- Another update --

Having played all day, I decided to see what would happen with a button_to instead, forgetting the ajax side of things. I put this in my code:

<%= button_to "Complete", completed_task_path(task.id) %>

And changed routes to:

match 'tasks/:id/completed' => 'tasks#co开发者_如何学运维mpleted', :as => :completed_task

Which worked a treat. Changing back to check_box_tag breaks it all again :(

Pretty much worked out it's the contents of my function. Having removed some code, I can update the css for a #:

 $('#complete_task_1').click(function() {
  $.ajax({
    success: function(data, textStatus, jqXHR) {
        $('#thing').css("color","red");
    }
  });
});

Any idea what I'd need to call my action?? J


If I understand what you're looking for (when the checkbox is checked or unchecked an Ajax request is sent to the server and the associated object is saved with the result of the checkbox), then yes you'll want to do it in Ajax.

With Rails 3 you're probably using jQuery (or, IMO, you should be). You'll need to implement a click event on the checkbox element. That click event, when it's fired, will do an Ajax call to your server. You'll want to do a PUT request since it's an update. You'll send the id of the object and the value of the checkbox.

There are a decent amount of sites that have examples of Rails and Ajax. This one (http://net.tutsplus.com/tutorials/javascript-ajax/using-unobtrusive-javascript-and-ajax-with-rails-3/) is good as it has you use the HTML 5 "data" fields which I like. There's also a bunch of similar questions here on SO. Here's one that's not Rails but will give you an idea of how to write the jQuery (AJAX Checkboxes).

Edit to answer question in comment

The checkbox can be wherever you want it since you're doing Ajax. If you want it on your index view, that's where you put it. Your checkbox will look something like this (please understand I'm not double checking my syntax or anything):

= check_box_tag 'complete_task_1', '', false, { 'data-href' => task_path(@task_1) }

Then your jQuery will look something like:

$('complete_task_1').click(function() {
  $.ajax({
    url: $(this).data('href'),
    type: 'PUT',
    dataType: 'html',
    success: function(data, textStatus, jqXHR) {
      // Do something here like set a flash msg
    }
  });
});

Second edit: I realized I forgot to actually send the value of the checkbox in the Ajax. You can do that and just call @task.update_attributes or you can make the url a specific method that only completes tasks.

Edit for updated question:

To explain my second edit, in order to update the task to be completed, you can do one of two things. You can either call a method that is expressly for setting the status attribute. Or you can call your normal, RESTful update method passing in :task => {:status => true} and call @task.update_attributes(params[:task]). You've chosen to do the former which, IMO, is fine.

So you have two problems. The first is that you aren't referencing the new route which points to your completed method. The second is that you aren't saving your object in the completed method.

To fix the first problem, you need to change the path your data-href attribute in the check_box_tag method points to. You don't want task_path. IIRC, you'll want completed_task_path(@task). The easiest way to find out the name of the path is to run rake routes in your Rails project's root directory.

To fix the second problem, just make sure to call @task.save at the end.

def completed 
  @task = Task.find(params[:id])
  @task.status = true
  @task.save
end


In your updated example, try replacing:

<%= check_box_tag 'complete_task_1', '', false, { 'data-href' => tasks_path(@task) } %>

with:

<%= check_box_tag 'complete_task_1', '', false, { 'data-href' => task_path(@task) } %>

Provided @task.id = 1, tasks_path(@task) returns /tasks.1, while task_path(@task) returns /tasks/1

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号