Catfish
Catfish

Reputation: 19284

Rails $.post call not containg params that i would expect

This used to work for me, but i've changed something and now it's not working and for the life of me i can't figure out what it is that i changed.

Basically I have a page where i'm implementing a jquery drag/drop feature and when the submit button is clicked, i'm passing some data to store the x and y position of all the elements that have been dragged/dropped.

You can see in my jquery snippet below that i'm using $.post. Then in my controller i save the data to the database.

The problem is that params[:application] is always nil. It used to contain the application data, but i've changed something and this no longer works.

Why does my ajax call not contain params[:application]?

This is the url that i'm hitting - /applications/1/edit

This is my jquery submit function

$('.organizer').submit(function(e) {
        e.preventDefault();
        e.stopPropagation();
        var dataToSubmit = $(this).serialize();
        var ids = [];
        var field_values = [];
        var x_values = [];
        var y_values = [];
        var success = true;

        console.log('dataToSubmit = '+dataToSubmit);

        $('.organizer .draggable').each(function() {
            // add the draggable value to an array
            field_values.push($(this).find('a').text().trim());
            ids.push($(this).find('a').data('id'));
            x_values.push($(this).closest('td').data('counter'));
            y_values.push($(this).closest('tr').data('counter'));
        });

        for(i = 0; i < field_values.length; ++i) {
            console.log('id = '+ids[i]);
            dataToSubmit += "&field_name="+field_values[i]+"&appfieldid="+ids[i]+"&xposition="+x_values[i]+"&yposition="+y_values[i];
            console.log(decodeURIComponent(dataToSubmit));
            $.post($(this).attr('action'), dataToSubmit).error(function() {
                success = false;
            }); 
        }

        // if all of the ajax calls were successful, show a success message
        if(success) {
            $('h1').after('<div class="nNote nSuccess"><p>Application Updated Successfully!</p></div>');
            $('.nSuccess').delay(5000).fadeOut();
        }

    });

Here's my controller method

# PUT /applications/1
  # PUT /applications/1.json
  def update
    @application = Application.find(params[:id])
    p params[:appfieldid]
    p params[:xposition]
    p params[:yposition]
    p params[:field_name]
    p params[:application] # WHY IS THIS ALWAYS NIL?
    app_fields = params[:application]
    p app_fields
    app_fields['application_field_attributes']["0"].merge!({"id"=>params[:appfieldid], "xposition"=>params[:xposition], "yposition"=>params[:yposition]})   #app_fields['application_field_attributes']['yposition'] = params[:yposition]
    p app_fields
    respond_to do |format|
      if @application.update_attributes(app_fields)
        #@application.application_details.xposition = params[:xposition]
        #@application.application_details.yposition = params[:yposition]

        @curr_app = ApplicationField.last
    format.html { render :nothing => true }
        format.json { head :no_content }
        format.js # WHY IS THIS NOT CALLED? INSTEAD I'M USING A SUCCESS CALLBACK ON THE $.POST METHOD
      else
        format.html { render action: "edit" }
        format.json { render json: @application.errors, status: :unprocessable_entity }
        format.js { render action: "update" }
      end
    end
  end

Here's the generated form markup

<form accept-charset="UTF-8" action="/applications/3" class="organizer" data-remote="true" id="edit_application_3" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="_method" type="hidden" value="put" /><input name="authenticity_token" type="hidden" value="3LOzuiL/PU6HypJ4OeN5H9yrX3Xyk0VT6XpcFYd1wY0=" /></div>
    <fieldset>
        <div class="widget fluid">
            <div class="whead"><h6>New Application</h6><div class="clear"></div></div>
            <table cellpadding="0" cellspacing="0" width="100%" class="tDefault tMedia" id="app_table">
                <thead>
                    <tr>
                        <td width="35%">First Half</td>
                        <td width="35%">Second Half</td>
                    </tr>
                </thead>
                <tfoot>
                    <tr>
                        <td colspan="6">
                            <input class="buttonS bBlue" name="commit" type="submit" value="Submit" />                  
                        </td>
                    </tr>
                </tfoot>
                <tbody>


                    <tr data-counter="0">
                        <td class="droppable nopadding" data-counter="0">
                                    &nbsp;
                                    &nbsp;
                        </td>           
                        <td class="droppable nopadding" data-counter="1">
                                    &nbsp;
                                    &nbsp;
                        </td>
                    </tr>           
                    <tr data-counter="1">
                        <td class="droppable nopadding" data-counter="0">
                                    &nbsp;
                                    &nbsp;
                        </td>           
                        <td class="droppable nopadding" data-counter="1">
                                    &nbsp;
                                    &nbsp;
                        </td>
                    </tr>           
                </tbody>
            </table>
        </div>
    </fieldset>
</form>

EDIT

Here's some more informational stuff:

# GET /applications/1/edit
  def edit
    @application = Application.find(params[:id])
  end

edit.html.erb

<%= form_for(@application, :html => {:class => "organizer"}, :remote => true) do |f| %>
...
<% @application.application_field.each_with_index do |f, i| %>              
    <tr data-counter="<%= i %>">
        <td class="droppable nopadding" data-counter="0">
        <% @application.application_field.each_with_index do |f2, i2| %>
                    <% if f2.yposition == i && f2.xposition == 0 %>
                        <ul class="subNav noborder">
                            <li class="draggable" style="height: 64px;">
                            <a value="#" data-id="<%= f.id %>" style="height: 47px;">
                                <span class="icos-list2 move"></span>
                                <span class="field_label"><%= f2.field_name %></span>
                                <% if f.field_type == 'textfield' %>
                                    <input type="text" class="textfield" name="textfield" />
                                <% elsif f.field_type == 'dropdown' %>
                                    <!-- TODO - fill in for dropdown -->
                                <% elsif f.field_type == 'checkbox' %>
                                    <!-- TODO - fill in for checkbox -->
                                <% end %> 
                            </a>
                            <%= link_to '<span class=icos-cross></span>'.html_safe, application_field_path(f), :class => 'remove_fields close', :method => :delete, :remote => true %>
                            </li>
                            </ul>   
                        <% end %>
                    <% end %>
                </td>           
            <td class="droppable nopadding" data-counter="1">
                   <% @application.application_field.each_with_index do |f2, i2| %>
                        <% if f2.yposition == i && f2.xposition == 1 %>
                            <ul class="subNav noborder">
                                <li class="draggable" style="height: 64px;">
                                <a value="#" data-id="<%= f.id %>" style="height: 47px;">
                                    <span class="icos-list2 move"></span>
                                    <span class="field_label"><%= f2.field_name %></span>
                                    <% if f.field_type == 'textfield' %>
                                        <input type="text" class="textfield" name="textfield" />
                                    <% elsif f.field_type == 'dropdown' %>
                                        <!-- TODO - fill in for dropdown -->
                                    <% elsif f.field_type == 'checkbox' %>
                                        <!-- TODO - fill in for checkbox -->
                                    <% end %>
                                </a>
                                <%= link_to '<span class=icos-cross></span>'.html_safe, application_field_path(f), :class => 'remove_fields close', :method => :delete, :remote => true %>
                                </li>
                            </ul>
                    <% end %>
                <% end %>
                </td>   
            </tr>           
        <% end %>
<% end %>

Upvotes: 1

Views: 135

Answers (2)

Catfish
Catfish

Reputation: 19284

By trying a bunch of things i remembered that i previously had, i figured out that by having

<%= f.fields_for :application_field do |field| %>
...
<% end %>

the params[:application] was passed to the controller.

I'm not exactly sure why this makes it work because i don't actually do anything with field.

Upvotes: 0

arieljuod
arieljuod

Reputation: 15838

does dataToSubmit include the application parameter? what should it be? an id? what?

what's the value of $(this).serialize() ?

dataToSubmit += "&field_name="+field_values[i]+"&appfieldid="+ids[i]+"&xposition="+x_values[i]+"&yposition="+y_values[i];

I guess you are missing an input field on the form with the name application, I can't see it on the form code.

Also, your request doesn't render the js response because you are not calling it with format 'script'. Do something like:

$.post($(this).attr('action'), dataToSubmit).error(
  function() {
    success = false;
  },'script');

that should make the request with js format

check the server log, it will tell you all parameters and format on the request, you don't need to puts everything on your controller, it's confusing

Upvotes: 1

Related Questions