views:

40

answers:

1

I am writing an application that will allow a user to add a component to a particular page in my DB, but am stuck on a little bit of the JS.

I have the form submitting just fine. I am stuck on how to "refresh" the container div that shows all of the current components tied to a page.

I am from a PHP background, so I know that I could write a method in my model and make an ajax call to it and just use jQuery to repopulate the container div. How would I do that in Rails? Or is there a better way of doing this?

Form:

<div class="add_component_block" style="display: none">
                <%= form_for page, :url => page_url(page), :class => "edit_page" do |p| %>
                        <div class="field">
                            <%= select_tag :component_id, options_for_select(@components.collect { |comp| [comp.name, comp.id] }), :include_blank => 'Select a Component' %>
                        </div>

                        <div class="action">
                            <%= p.submit :Submit %>
                        </div>
                    <% end %>
            </div>

jQuery:

$('#page_submit').click(function(e){
        $.ajax({
            url: $('.edit_page').attr('action'),
            type: "PUT",
            data: "component_id=" + $('#component_id').val(),
            success: function(data){
                location.reload();
            }
        });
        return false;
    });

Thanks in advance for the help!

Working Code

Controller:

def create
    if !params[:component_id]
      @component = Component.new(params[:component])

      respond_to do |format|
        if @component.save
           params[:page_id].each { |p|
            PagesComponent.create({ :page_id => p, :component_id => @component.id })
           } unless params[:page_id].nil?
          format.html { redirect_to(@component, :notice => 'Component was successfully created.') }
          format.xml  { render :xml => @component, :status => :created, :location => @component }
        else
          format.html { render :action => "new" }
          format.xml  { render :xml => @component.errors, :status => :unprocessable_entity }
        end
      end
    else
      @component = PagesComponent.new(:page_id => params[:page_id], :component_id => params[:component_id])

        if @component.save
          @all_components = Page.where("id = ?", params[:page_id])
          @component_list = []

          @all_components.each do |pc|
            pc.components.each do |c|
              @component_list << c.name
            end
          end

          render :json => @component_list
        end
    end
  end

jQuery:

$('#page_submit').click(function(){
        $('.add_component_block').hide();
        $.ajax({
            url: $('.edit_page').attr('action'),
            type: "POST",
            data: "component_id=" + $('#component_id').val(),
            success: function(data){
                console.log(data)
                $('#page_components').empty();
                $.each(data, function(i, itemData){
                    $('#page_components').append("Name: " + itemData + "<br />")
                });
            }
        });
        return false;
    });
+1  A: 

location.reload() is too big a hammer if you are just wanting to update what is in the #componend_id div. Rails is no different from PHP in this regard. When it receives a post request from the client with an XmlRpc header, it then responds with whatever you tell it to:

@my_data = MyModel.find(whatever)

if request.xhr? do
  respond_to do |format|
    format.html        # if this method responds to HTML

    format.xml do
      render @my_data.to_xml, :layout => false
    end

    format.json do
      render @my_data.to_json, :layout => false
    end
  end
end

When the response is received in your success handler, you can simply populate the div with the data that is shipped back, either as XML or JSON (at least, that's how I would ship it back).

You may want to use dataType: "json" in your $.ajax hash to make sure the accept headers are set properly. Then simply set $('#component_id').html(data['whatevercameback']).

To see the entire round trip, check it out in Firebug, which will show you what you are posting and what Rails is sending back.

Steve Ross
thanks for the help! I put in my edits above to what I ended up doing... however, I have a new issue. When the post is done I am rewriting my HTML with the data that comes back, but the list that comes back is grouped together by name versus the order in the DB... anyway to fix this? My code is included above as well
dennismonsewicz
Hard to know what your model looks like, but is it possible that natural and alphabetical ordering are coincidentally the same? Rails does nothing to alter the order of the result set unless you specify the :order parameter. Look at your log/development.log and you can examine the SQL that's being used. BTW: Congrats on getting to this point. You're doing great.
Steve Ross