Rails 3 - respond_to as JS and flash message - javascript

After send a form I will process a data from form and wanna to render an action as JS. This work me.
But + this functionality I would like to add a flash message yet. I try to do it as follows:
respond_to do |format|
if #save.update_attributes(params[:data])
format.js {
flash[:notice] = 'The article was successfully updated.'
render :update do |page|; page << "$('#my_div').html('#{escape_javascript(render(:partial => 'article'))}');" end
}
format.html {}
else
format.html { render :action => "edit" }
format.xml { render :xml => #data.errors, :status => :unprocessable_entity }
end
Now the flash message is not displayed. Could anyone help me, why not? I tried the line with flash[:notice] move to out of format.js block, but the is still not displayed...
Could you help me, please, why?r

I guess you can use the point 2.2.10 of the documentation :
http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
render :js => "$('#my_div').html('#{escape_javascript(render(:partial => 'article'))}');"

Related

Clearing my ajax form in rails

I'm trying to clear the form if its submitted but the problem is my controller handles all the validation.
The AJAX response in contact.js.haml simply makes use of flashes not being defined if its invalid data.
/contact.js.haml
$("#new_message").replaceWith("#{j(render partial:'contact_mailer/contact_me', locals: {object: #message, notice: #notice} )}")
The controller sets the notice if needed
class MessagesController < ApplicationController
def contact
#message = Message.new(params[:message])
respond_to do |format|
if #message.valid?
flash.now[:notice] = 'Message was sent successfully.'
ContactMailer.contact_me(#message)
format.html { redirect_to contact_path, notice: 'Message was sent successfully.' }
format.js
else
format.html { redirect_to contact_path }
format.js
end
end
end
end
The issue is on a successful message send, the form still has the same data, allowing the user to spam it
I know this can be solved with JSON or XML to send the data but is there a way without!
*edit screenshot of reset() not working
- if !#message.errors.any?
$(':input').not(':button, :submit, :hidden').val('')
haml didn't work before so I assumed it wouldn't but it did.
A little cleaner: just reset the form (a plain javascript function).
In short:
$('form')[0].reset
This resets the first form on the page.
However, see this answer:How come form.reset() doesn't work after postback on this page? It will reset the form to the values it received. And you send it from the server, with values!!!!
So the fix is dead-easy, in your MessagesController write
def contact
#message = Message.new(params[:message])
respond_to do |format|
if #message.valid?
flash.now[:notice] = 'Message was sent successfully.'
ContactMailer.contact_me(#message)
#message = Message.new
format.html { redirect_to contact_path, notice: 'Message was sent successfully.' }
format.js
else
format.html { redirect_to contact_path }
format.js
end
end
end
So before rendering, start with a fresh, new message, and your form will be ok :)
On a general note: your naming and grouping is generally very confusing and not very structured. You should work on that.

Rails Edge Guides, AJAX example- why use both 'format.js' and 'format.json'?

In the "Working With Javascript" section of the Rails Edge Guides, an example is given of how to structure a 'create' action inside a 'User' controller, in order to integrate AJAX into the creation action:
# app/controllers/users_controller.rb
# ......
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.js {}
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I've read here that both 'format.js' and 'format.json' are needed, because Javascript and JSON are different types of response. My question is, if both formats are specified in the first half of the 'create' action's if statement, why aren't both also needed in the 2nd half? Does this mean that Javascript uses the 'create.js.erb' file on success, but not on failure?
Yes, you are correct. Based on skimming the guide, it looks like you don't want to do anything with js in the case of failure. If you were to put
format.js {}
in the failure block as well, then it would try to execute the render #user portion, which would probably cause an error anyway.
If you really did want to execute a js block in the event of failure, you could just do it the same way as for the other formats.

Rails 3, comments nested resource saving 1 instance 4 times

I have a strange problem. I have 2 models Issue, Comment. Comments is nested inside Issues so for that I have the create action in comments controller as follows:
def create
#issue = Issue.find(params[:issue_id])
#comment = #issue.comments.create!(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
format.js #create.js.erb
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
And my create.js.erb:
var new_comment = $("<%= escape_javascript(render(:partial => #comment))%>").hide();
$('#comments').prepend(new_comment);
$('#comment_<%= #comment.id %>').fadeIn('slow');
$('#new_comment')[0].reset();
Issue.rb
class Issue < ActiveRecord::Base
attr_accessible :category, :description, :title
has_many :comments
end
Comment.rb
class Comment < ActiveRecord::Base
attr_accessible :body, :issue_id
belongs_to :issue
end
routes.rb
resources :comments
resources :issues do
resources :comments
end
Problem: When I create a comment for which is a form partial residing on views/issues/show.html.erb. The comment gets created 4 times in the db.
I couldn't locate what the problem was and whats causing it. Please help
First, I would build the associated comment:
#comment = #issue.comments.build(params[:comment])
And then I would save the comment instance
#comment.save
And also check the Javascript, maybe you are having some problems with event bubbling and the event is being triggered twice.
I actually was working on some old Rails version where the js files were put inside the /public/assets and that was the reason for that weird behaviour. I deleted all the files inside the /public/assets folder and the app works fine now.

Rails double render

I know this isn't valid code, but is there a way to do something like this in Rails?:
render "$('#dialog').replaceWith(#{render :action => 'new.html.erb'});"
What I'm trying to do basically is replace the contents of a JS dialog with what is/would be returned from calling render 'new.html.erb'.
Edit for #Devin M:
controller action:
def new
#act = Act.new(:user_id => current_user.id)
end
def create
#act = Act.new(params[:act])
if #act.valid?
#act.save
else
render :action => :new
end
end
new.js.erb:
$('#dialog').replaceWith("<%= escape_javascript(render(:action => 'new.html.erb')) %>");
Full error:
Showing app/views/acts/new.js.erb where line #1 raised: undefined method `formats' for nil:NilClass
You should split this code out into a seperate view since including it in the controller would go against the ideas of MVC. I would update the controller to respond to JS requests using some code like this in the action I wanted to modify:
respond_to do |format|
format.html { redirect_to #item }
format.js
end
And create a view like this with the extenstion .js.erb:
$('#dialog').replaceWith("<%= escape_javascript(render :partial => "new.html.erb", :locals => { :act => #act }) %>");
You can then trigger this JS with a remote link to the action or by adding your own UJS.

AJAXy action accessible via "normal" request

Greetings,
I have an application which contains a calendar as alternative index view for Courses (Project has_many Courses). There I have two arrows for navigating to the next/previous month, it works via AJAX. Now, that's my action for updating the calendar:
def update_calendar
#project = Project.find params[:id]
#date = Date.parse(params[:date]).beginning_of_month
#courses = #project.courses.all(:conditions => {:date => (#date - 1.month)..(#date + 1.month)})
respond_to do |format|
# format.html { redirect_to :action => 'index' }
format.js { render :partial => 'calendar', :locals => {:calendar_date => #date, :courses => #courses} }
end
end
The important part is format.js { ... }. I thought it should just answer js/AJAX requests, but it doesn't. It renders the partial when I hit the URL http://localhost:3000/projects/1/update_calendar?date=2010-08-01 for example. I don't want that behaviour, I just want it to answer correctly when it's coming in via AJAX. Do I need to use request.xhr?? And what is format.js { ... } supposed to do than?
Best regards
Tobias
You need to tell it what you want to happen when someone goes to that action with an html request, ie you need to put your format.html block back in. If you don't have the braces it will do the default behaviour which is to show the update_calendar view. You probably want to redirect to a different action though.

Categories