Topic: Radio Buttons and observe_field

Hello!

My intention is to have a list of records from a query and some sorting options at the top.  I'd like those options to be ajax radio buttons where when checked they will run the correct query and change the sort order of the items being displayed.  I've looked at the api but, I'm pretty  new with Ruby on Rails and Ajax.  Does anyone have any suggestions as to how to do this?

Thanks!

Re: Radio Buttons and observe_field

You may want to use the observe_form helper. You can then use RJS in the resulting action to update the list of records. I can give you more deteails if you need it.

Last edited by ryanb (2006-11-06 11:33:22)

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Thank you for the quick response.  I am new at this so an example would be awesome.  I just need to know how to setup the observe_form().  Do I just enclose the entire form in observe_form()?  Thank you again for the help!

Re: Radio Buttons and observe_field

observe_form will generate some javascript, so you would simply need to output it. Probably after the form has been made. Like this:

<%= start_form_tag({}, {:id => 'sort_form'}) %>
  <%= radio_button_tag :sort_column, :foo %> Foo
  <%= radio_button_tag :sort_column, :bar %> Bar
<%= end_form_tag %>
<%= observe_form :sort_form, :url => { :action => 'sort', :query => params[:query] } %>

The start_form_tag parameters look a little weird. This is because we aren't setting the URL of the form, just the 'id' HTML attribute so we can reference it.

When a radio button is clicked/changed, it will call the sort action of the controller. You can use params[:sort_column] to determine how to sort the query, then use RJS to update the list.

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

I have implemented what you posted.  One more (and hopefully last) question.  Don't I need to tell it what div to updated?  Or by calling the action will it just refresh the entire page with the new content?

Re: Radio Buttons and observe_field

You specify the div in the RJS like this:

# in rjs file
page['some_div'].replace_html :partial => 'items'

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Got it.  Thank you!

Re: Radio Buttons and observe_field

Ok, I've worked on this, but for some reason it's not updating the results.  Below is what I have so far:

View:
<%= start_form_tag({}, {:id => 'sort_form'}) %>
    <%= radio_button_tag :sort_column, :date %> Date
    <%= radio_button_tag :sort_column, :score %> Score
<%= end_form_tag %>
<%= observe_form :sort_form, :url => { :action => 'links', :sort => params[:sort] } %>

Controller:
def links
    user = User.find_by_login(params[:username])
    feeds_priv = Feed.find(:all, :conditions => ["user_id = ? and visible = 1", user.id], :include => 'source')
    feeds = Feed.find(:all, :conditions => ["user_id = ?", user.id], :include => 'source')
    if params[:sort] == 'score'
      sort = 'friend_count'
    else
      sort = 'created_at'
    end
    case params[:filter]
      when 'both'
      items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      when 'yours'
        items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      when 'friends'
        items = Item.find_by_sql "Long SQL Query

        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      end
  end

Is this enough information for some tips?

Re: Radio Buttons and observe_field

The observe_form automatically sends the form fields to the action, so you should call params[:sort_column] (the name of the radio buttons) in the link action.

Also, if nothing seems to be happening when clicking a button, go to /my_controller/links?sort_column=date directly in the browser and see if you are getting javascript back.

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Ok, I have updated what you said and it's working like a charm... in the url... but it still not updating the items automatically when a radio button is selected.  Now I should say that right now the action is for the full page not a partial so when you go to controller/links it should refresh the entire page.

Also, I don't think this matters, but I have other filter options such as whether you want to display only your items or only your friends items or both.  They are passed through the url as well... and that's where the 'case' comes into play.  I'd love to ajax the whole thing so I was planning on figuring out this sort option and then trying to retrofit it to the other filter options.  Would you recommend combining the two into one form? and then making the display div a partial?

View:
<%= start_form_tag({}, {:id => 'sort_form'}) %>
    <%= radio_button_tag :sort_column, :date %> Date
    <%= radio_button_tag :sort_column, :score %> Score
<%= end_form_tag %>
<%= observe_form :sort_form, :url => { :action => 'links', :sort => params[:sort_form] } %>

Controller:
def links
    user = User.find_by_login(params[:username])
    feeds_priv = Feed.find(:all, :conditions => ["user_id = ? and visible = 1", user.id], :include => 'source')
    feeds = Feed.find(:all, :conditions => ["user_id = ?", user.id], :include => 'source')
    if params[:sort_column] == 'score'
      sort = 'friend_count'
    else
      sort = 'ts'
    end
    case params[:filter]
      when 'both'
      items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      when 'yours'
        items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      when 'friends'
        items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
      end
  end

Re: Radio Buttons and observe_field

cantinflas83 wrote:

Would you recommend combining the two into one form? and then making the display div a partial?

Yep. It's fairly easy to ajaxify this. You just need to create a links.rjs file (instead of links.rhtml) and update the div as I showed above.

If you have more fields, you may want to use remote_form_tag instead of start_form_tag + observe_form. Then you can have an "Update" submit button which will call the link action along with the RJS file. I can post some code if you need me to.

Last edited by ryanb (2006-11-06 17:19:19)

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Let me first say that I appreciate all your help very much!  If you don't mind I'd like to have some code for reference.  I learn best by reverse engineering and viewing examples. smile

Also, in creating the links.rjs file, do I just rename the file with the .rjs extension?  Is it just a view file in essence?  Or are there certain things I should or should not include in that file?  Do I need to have a file that includes the .rjs file, or does the controller just display the .rjs as it would with an .rhtml file with the same name?

Thanks!

Re: Radio Buttons and observe_field

cantinflas83 wrote:

Let me first say that I appreciate all your help very much!  If you don't mind I'd like to have some code for reference.  I learn best by reverse engineering and viewing examples. smile

Sure, no problem.

cantinflas83 wrote:

Also, in creating the links.rjs file, do I just rename the file with the .rjs extension?  Is it just a view file in essence?  Or are there certain things I should or should not include in that file?

It's actually more like a ".rb" file as it is straight Ruby, not HTML with embeded ruby. You need to move the HTML code into a partial (whatever you want to replace inside the div) then just create a links.rjs file with this single line:

page[:div_name].replace_html :partial => 'my_partial'

Of course you'll need to replace div_name and my_partial with the proper values. The div_name would be the dom_id of the div element you want to replace.

cantinflas83 wrote:

Do I need to have a file that includes the .rjs file, or does the controller just display the .rjs as it would with an .rhtml file with the same name?

As long as it has the same name as the action, and is located in the controller's view directory, it will load it automatically (just like it would automatically load links.rhtml).

Here's some code.

# view
<%= form_remote_tag :url => { :action => 'links' } %>
  <%= radio_button_tag :sort_column, :date %> Date
  <%= radio_button_tag :sort_column, :score %> Score
  ...
  <%= submit_tag 'Update' %>
<%= end_form_tag %>
<div id="items">
  <%= render :partial => 'items' %>
</div>

# controller
  def links
    user = User.find_by_login(params[:username])
    feeds_priv = Feed.find(:all, :conditions => ["user_id = ? and visible = 1", user.id], :include => 'source')
    feeds = Feed.find(:all, :conditions => ["user_id = ?", user.id], :include => 'source')
    if params[:sort_column] == 'score'
      sort = 'friend_count'
    else
      sort = 'ts'
    end
    case params[:filter]
      when 'both'
      @items = Item.find_by_sql "Long SQL Query
        ORDER BY #{sort} DESC
        LIMIT 0 , 30"
        #...
      end
  end

# links.rjs
page[:items].replace_html :partial => 'items'

# _items.rhtml partial
<% for item in @items %>
  ....
<% end %>


Does that make sense?

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

It all makes sense I think, but when I set it up that way the 'Update' button does not return any action.  It's as if it's not sending any information.  Is there a debugging method I can use?

Re: Radio Buttons and observe_field

Try calling the /my_controller/links?sort_column=date in the web browser. It should be returning JavaScript.

Oh yeah, and don't forget to include the javascript files into the header:

<%= javascript_include_tag :defaults %>

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Ok, the javascript seems to be working... If I type it directly into the url everything works fine. The 'update' button is the only thing that is not working.  Here is my view:

<div id="topnav1" style="border: 1px solid #ccc; padding:5px; margin:5px">
    <%= form_remote_tag :url => { :action => 'links' } %>
        Sort Options:
        <%= radio_button_tag :sort_column, :date %> Date
        <%= radio_button_tag :sort_column, :score %> Score
        | Filter Options:
        <%= radio_button_tag :filter, :yours %> Your Items
        <%= radio_button_tag :filter, :friends %> Friends Items
        <%= radio_button_tag :filter, :both %> Both
        <%= submit_tag 'Update' %>
    <%= end_form_tag %>
</div>

<div id="links_update_div">
    <%= render :partial => 'links_update' %>
</div>

links.rjs:
page[:links_update_div].replace_html :partial => 'links_update'

and the controller is the same...  Also, I have the include :defaults in there as well.  Argg wink

Re: Radio Buttons and observe_field

cantinflas83 wrote:

Ok, the javascript seems to be working... If I type it directly into the url everything works fine.

Are you getting JavaScript back in the browser? Or are you getting HTML? It should be JavaScript text. Make sure there's no links.rhtml file anymore, as this will override the links.rjs file from being rendered.

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

I'm just getting HTML... I have not removed the links.rhtml file.  That file contains this:

<div id="topnav1" style="border: 1px solid #ccc; padding:5px; margin:5px">
    <%= form_remote_tag :url => { :action => 'links' } %>
        Sort Options:
        <%= radio_button_tag :sort_column, :date %> Date
        <%= radio_button_tag :sort_column, :score %> Score
        | Filter Options:
        <%= radio_button_tag :filter, :yours %> Your Items
        <%= radio_button_tag :filter, :friends %> Friends Items
        <%= radio_button_tag :filter, :both %> Both
        <%= submit_tag 'Update' %>
    <%= end_form_tag %>
</div>
<div id="links_update_div">
    <%= render :partial => 'links_update' %>
</div>

Should I put that into the partial? Along with this:
<% for item in @items %>
  ....
<% end %>

Re: Radio Buttons and observe_field

Oh, I see. Are you using the same action for both the full page and the JavaScript updating? I assumed the "links" action was used for only the javascript updating.

That's okay if you want to keep it on the same action though. You just need to add this to the end of the links action in the controller:

responds_to do |format|
  format.html
  format.js
end

Now the RJS file should be called when the action is triggered by JavaScript.

Railscasts - Free Ruby on Rails Screencasts

Re: Radio Buttons and observe_field

Got it!  Thank you for all the help!