Reputation: 19284
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="✓" /><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">
</td>
<td class="droppable nopadding" data-counter="1">
</td>
</tr>
<tr data-counter="1">
<td class="droppable nopadding" data-counter="0">
</td>
<td class="droppable nopadding" data-counter="1">
</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
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
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