Topic: problems with ajax request passing an object...

I am having what I am sure isn't a difficult problem but I can't seem to find what exactly is wrong...

I am creating a text link using link_to_remote to order a list of items based on a different parameter (say the title instead of the category) and then place that reordered list back on the page.

Somewhere along the way I am not getting the variable containing the new list to pass - it keeps showing up as a nil object...

The Error:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occured while evaluating nil.each_with_index
(identifies the render_collection_of_partials line in the VIEW below)

Here is the code:

*** VIEW

<%= link_to_remote('<div id="todo_item_title_hd">Title</div>', :update => "not_done_items_wrapper", :url => {:action => "sort_by"}) %>

<ul id="not_done_items" style="list-style-type: none;">
    <div id="not_done_items_wrapper">
         <%= render_collection_of_partials "display", nil, 'item' => @not_done %>
    </div>
</ul>


*** CONTROLLER

def sort_by
   @not_done = Todo.order
   render :update do |page|
      page.replace_html("not_done_items_wrapper", :partial => "display", :object => @not_done)
   end
end


*** MODEL (todo)

def self.order
    find_all("done=0", "description")
end


What's the broken puzzle piece? Thanks!

Re: problems with ajax request passing an object...

What does the display partial look like? At one point you are passing a single Todo object to it, and another point you are passing an array of Todo objects to it.

BTW, there are a few things which have been deprecated. The render_collection_of_partials should be:

render :partial => 'display', :collection => @not_done

And find_all should be:

def self.order
    find(:all, :conditions => "done=0", :order => "description") # I'm guessing the last one is the order?
end

Railscasts - Free Ruby on Rails Screencasts

Re: problems with ajax request passing an object...

Here is the _display partial:

<li id="item_<%= @item.id %>"
    <% if item.done == 0 %>
        class="not_done_items"
    <% else %>
        class="done_items"
    <% end %>
    style="color: #<%= @item.color.color_code %>">
    <ul style="list-style-type:none;" >
        <li id="todo_item_title"><%= item.description %></li>
        <li id="todo_item_category"><%= item.category.category_name %></li>
        <li id="todo_item_assigned_to"><%= item.initial.initials %></li>
        <li id="todo_item_options"><%= link_to_remote("Details", :url => {:action => "view_details", :id => item.id}, :complete => "Element.show('details')") %>
            <%= link_to("Edit", :action => "edit", :id => item.id) %></li>
    </ul>
    <%= draggable_element "item_#{
    item.id}" %>
</li>


The <ul> inside of the main <ul><li> tags are the way that I came up with to organize the content into a table-like structure and still make it sortable...

On a side note, how do you wrap your ruby code on the forum so that it comes out in a container like your posts?

Re: problems with ajax request passing an object...

You can wrap code with [ code=ruby ] and [ /code ] tags (remove the spaces).

You are referencing both "@item" and "item" in the partial, but probably only one of those is getting set in the first code snippet, and neither one of those is getting set when you call the partial from the RJS.

Actually, this will be easier if you rename "_display.rhtml" partial to "_item.rhtml". So, now when you pass the :object or :collection parameter, it will be mapped to the variable named "item" in the partial (the same name as the partial).

# in _item
<li id="item_<%= item.id %>"
    <% if item.done == 0 %>
        class="not_done_items"
    <% else %>
        class="done_items"
    <% end %>
    style="color: #<%= item.color.color_code %>">
    <ul style="list-style-type:none;" >
        <li id="todo_item_title"><%= item.description %></li>
        <li id="todo_item_category"><%= item.category.category_name %></li>
        <li id="todo_item_assigned_to"><%= item.initial.initials %></li>
        <li id="todo_item_options"><%= link_to_remote("Details", :url => {:action => "view_details", :id => item.id}, :complete => "Element.show('details')") %>
            <%= link_to("Edit", :action => "edit", :id => item.id) %></li>
    </ul>
    <%= draggable_element "item_#{
    item.id}" %>
</li>

So in the view you will do this to render the items:

<%= render :partial => 'item', :collection => @not_done %>

I'm not sure exactly what you want to do in the rjs portion, but probably the same thing?

page.replace_html "not_done_items_wrapper", :partial => "display", :collection => @not_done

Lastly, since you are specifying the div to update in this RJS, you don't need to specify it in the link_to_remote call.

<%= link_to_remote('<div id="todo_item_title_hd">Title</div>', :url => {:action => "sort_by"}) %>

Does that work for you?

Railscasts - Free Ruby on Rails Screencasts

Re: problems with ajax request passing an object...

yeah, actually that works great - good to know those functions are depricated also...

I have one problem at moment. Everything sorts great but once I choose to sort the list I lose the sortable funtionality. I can still drag the items but they just stay wherever they are dropped on the page and don't update at all.

I used firebug to check the html being generated and it seems that when I call a sort it is adding a second copy of all the items. So if I start with 3 todo items (sorted by their position column in the database) then choose to sort them by their category, I then end up with 6 items in the html (only 3 viewable in the browser) - ie each item now has a double...

I can't come up with a reason for this...

Re: problems with ajax request passing an object...

Not sure what the problem is. If you aren't seeing duplication in the browser window, it's probably just Firefox not replacing the HTML (from Javascript) properly There probably isn't any duplication.

I'm not sure if sorting is designed to work with dynamic list items, so it may be just a limitation of prototype/scriptaculous.

Railscasts - Free Ruby on Rails Screencasts