I have a Rails view (recipes/new) which allows users to enter a new recipe. In that view, the user can select items from another model, ingredients. I wanted a way for the users to add a new ingredient without leaving the recipe form.
I created a link for new ingredients which loads a JQuery modal box. Here is the code in my recipes.js
file which drives the modal:
assets/javascripts/recipes.js
this code from @coreyward's answer - see Jquery modal windows and edit object for details - thanks, corey!
$(function(){
var $modal = $('#modal'),
$modal_close = $modal.find('.close'),
$modal_container = $('#modal-container');
$('a[data-remote]').live('ajax:beforeSend', function(e, xhr, settings){
xhr.setRequestHeader('accept', '*/*;q=0.5, text/html, ' + settings.accepts.html);
});
$('a[data-remote]').live('ajax:success', function(xhr, data, status){
$modal
.html(data)
.prepend($modal_close)
.css('top', $(window).scrollTop() + 40)
.show();
$modal_container.show();
});
$('.close', '#modal').live('click', function(){
$modal_container.hide();
$modal.hide();
return false;
});
});
My link in the recipes/new.html.erb:
<%= link_to 'New ingredient', new_ingredient_path, :remote => true %>
This works great, in the sense that it loads the modal form with the new ingredient form in there. I can fill out the form, and if the ingredient is saved, I call another function from my controller to close the modal:
ingredients_controller.rb
def create
if @ingredient.save
respond_to do |format|
format.js { render :js => "close_modal();" }
end
end
end
My problem is when the form is not filled out correctly. The user clicks and gets no feedback that there are any errors/missing fields, etc... I would like to reload the ingredient form in the popup box, which will render a shared errors partial:
ingredients/new.html.erb
<%= form_for @ingredient, :remote => true do |i| %>
<%= render 'shared/ingredient_error_messages' %>
<div class="field">
<%= i.label :name %>
<%= i.text_field :name %>
</div>
<div class="field">
<%= i.label :srm %>
<%= i.text_field :srm %>
</div>
<div class="field">
<%= i.label :price %>
<%= i.text_field :price %>
</div>
<div class="actions">
<%= i.submit "Save ingredient" %>
</div>
<% end %>
shared/_ingredient_error_messages.html.erb
<% if @ingredient.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@ingredient.errors.count, "error") %>
prohibited this recipe from being saved:</h2>
<p>There were problems with the following fields:</p>
<ul>
<% @ingredient.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
What's the best way to get this to work? I can easily create another JS function and call it from the controller if the save is not successful, but I can't find a way to pass in anything but straight text/html. Is there a way, in the controller, I can parse and output to a function the contents of my 'new' view? Is there a better/cleaner way to do this?
I have a Rails view (recipes/new) which allows users to enter a new recipe. In that view, the user can select items from another model, ingredients. I wanted a way for the users to add a new ingredient without leaving the recipe form.
I created a link for new ingredients which loads a JQuery modal box. Here is the code in my recipes.js
file which drives the modal:
assets/javascripts/recipes.js
this code from @coreyward's answer - see Jquery modal windows and edit object for details - thanks, corey!
$(function(){
var $modal = $('#modal'),
$modal_close = $modal.find('.close'),
$modal_container = $('#modal-container');
$('a[data-remote]').live('ajax:beforeSend', function(e, xhr, settings){
xhr.setRequestHeader('accept', '*/*;q=0.5, text/html, ' + settings.accepts.html);
});
$('a[data-remote]').live('ajax:success', function(xhr, data, status){
$modal
.html(data)
.prepend($modal_close)
.css('top', $(window).scrollTop() + 40)
.show();
$modal_container.show();
});
$('.close', '#modal').live('click', function(){
$modal_container.hide();
$modal.hide();
return false;
});
});
My link in the recipes/new.html.erb:
<%= link_to 'New ingredient', new_ingredient_path, :remote => true %>
This works great, in the sense that it loads the modal form with the new ingredient form in there. I can fill out the form, and if the ingredient is saved, I call another function from my controller to close the modal:
ingredients_controller.rb
def create
if @ingredient.save
respond_to do |format|
format.js { render :js => "close_modal();" }
end
end
end
My problem is when the form is not filled out correctly. The user clicks and gets no feedback that there are any errors/missing fields, etc... I would like to reload the ingredient form in the popup box, which will render a shared errors partial:
ingredients/new.html.erb
<%= form_for @ingredient, :remote => true do |i| %>
<%= render 'shared/ingredient_error_messages' %>
<div class="field">
<%= i.label :name %>
<%= i.text_field :name %>
</div>
<div class="field">
<%= i.label :srm %>
<%= i.text_field :srm %>
</div>
<div class="field">
<%= i.label :price %>
<%= i.text_field :price %>
</div>
<div class="actions">
<%= i.submit "Save ingredient" %>
</div>
<% end %>
shared/_ingredient_error_messages.html.erb
<% if @ingredient.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@ingredient.errors.count, "error") %>
prohibited this recipe from being saved:</h2>
<p>There were problems with the following fields:</p>
<ul>
<% @ingredient.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
What's the best way to get this to work? I can easily create another JS function and call it from the controller if the save is not successful, but I can't find a way to pass in anything but straight text/html. Is there a way, in the controller, I can parse and output to a function the contents of my 'new' view? Is there a better/cleaner way to do this?
Share Improve this question edited May 23, 2017 at 11:50 CommunityBot 11 silver badge asked Feb 28, 2012 at 22:16 JimJim 2,3101 gold badge19 silver badges44 bronze badges 5- 1 Sounds like you are trying to do what this guy was trying to do: stackoverflow./questions/6374664/… – PhillipKregg Commented Feb 28, 2012 at 22:27
- @PhillipKregg - man, I searched around for similar questions and found a few which didn't quite fit. Somehow I missed the one you linked to. I should be able to figure this out based on that example code. What's SO best practice now, delete this question or what? – Jim Commented Feb 28, 2012 at 22:36
- Well, you can delete it if you want. Or you can leave it up and it will provide another resource for folks who are looking for the same info. I can put the link as an answer at the bottom and you can mark it as the solution. It's a good resource, and it will give me the free fake points for not doing anything. A win-win. :) – PhillipKregg Commented Feb 28, 2012 at 22:41
- @PhillipKregg - just got everything up and running with my project. This is my first time integrating AJAX/JS stuff, and I was not aware of the power of the js.erb files. Thanks for the enlightenment! :) – Jim Commented Feb 28, 2012 at 22:50
- No problem - best of luck with your project. – PhillipKregg Commented Feb 28, 2012 at 23:21
1 Answer
Reset to default 3Here is a link to a github Rails JQuery-Modal form that was designed by Ramblex to do this very thing:
https://github./ramblex/modal-form
Here is the respective SO question that it solved (so you can upvote his answer): Rails and modal jquery dialog form