0

I'm in the middle of my first rails project, and have reached the stage where I want to change the ORDER BY of my models' index depending on the value of a SELECT tag.

I have the following onchange in my index.html.erb

<div id="sortBy">
        <span>Sort by:</span>
        <%= select_tag "sort_by", options_for_select([ "Newest first", "Oldest first" ], "Newest first"), { :onchange => "changeSortOrderJs(this.value)" } %>
</div>

That should update this:

<% @horses.each do | horse | %>
   <%= horse.name %>
<% end %>

This calls the following method in my coffeescript asset ( prefixed with @ since it is an anon function):

@changeSortOrderJs = (val) ->
  $.ajax
    type: 'GET'
    url: '/horses'
    data: order: val

This maps to my index action in the HorsesController

def index
        order = params[:order]

        if(order == nil) 
            order = 'Newest first'
        end

        @horses = Array.new

        if order == 'Newest first'

            @horses = Horse.all.order("created_at DESC")

        elsif order == 'Oldest first'

            @horses = Horse.all.order("created_at ASC")
        end

        //tried this later but didn't work either
        respond_to do |format|
            format.html
        end
    end

I can see in my development.log that is working and the @horses are being populated in their correct order. But the view does not refresh.

If I use respond_with(@horses) and then a success callback in the ajax call, i.e.

@changeSortOrderJs = (val) ->
  $.ajax
    type: 'GET'
    url: '/horses'
    data: order: val
    success: (result) ->
      $('body').html(result)

then it does work and the horses get reordered. But I would rather not replace the whole body this way.

I thought the whole point with instance variables was that you could redefine them and the view would update automatically?

1
  • BTW, :onchange => "changeSortOrderJs(this.value)" is sort of old school, you'd be better off with something like $('#sortBy select').change -> .... Commented Nov 20, 2014 at 18:48

1 Answer 1

1

The instance variables don't just magically update the page. You have to use the success function like you're doing in the last segment of code. If you want the instant update you should look into using Knockout.js or something like that

Also, if you plan on rendering partials you'll have to do so outside of a Coffeescript file. For example, in your controller do:

respond_to do |format|
  format.js
end

And app/controllers/horses/index.js do:

container = $('#your_div_here');

<% @horses.each do |horse| %>
  container.prepend( "<%= j render( :partial => 'horses/horse', :locals => { :horse => horse } ) %>" );
<% end %>
Sign up to request clarification or add additional context in comments.

4 Comments

Ah, OK. Is there any way I can make the callback just return the horses HTML rather than absolutely everything?
Yes, but if you're planning on rendering a bunch of partials you'll have to do so outside of a Coffeescript file since you won't have access to the render method. See my edit to the answer.
Thanks for the edit. Should I be looking at making a horses (rather than horse) partial to avoid multiple renders?
Nope. the file should be named index.js, so you should be good. You can also remove the loop and render a single partial as you suggested if you wish. You'll just have to loop through the horses in the partial I guess.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.