RJS & Ajax question


#1

Hi,

I’m trying to convert an older Rails application to use Ajax. I’ve
already moved my edit and show actions so that, instead of displaying as
separate pages, they appear in a

on my list view.

However, I have two problems:

  1. When the user saves the changes, I want to put all the ajax changes
    in an RJS template. However, form_remote_tag :url =>{:action => ‘save’}
    does not appear to call the save.rjs template.

I can get the changes to fire by placing them in the save action itself,
using the following:

render :update do |page|
page[:scratchpad].hide
page.replace ‘todo’, :partial => ‘table’, :locals => {:items =>
items}
page[“row#{@item.id}”].visual_effect :highlight, :startcolor =>
#fff00’, :duration => 5
page.replace_html ‘flash’,

#{@item.title} successfully updated!

page[:flash].show
page[:flash].visual_effect :pulsate, :queue => {:position => 'end', 

:scope => ‘flash’}
page[:flash].visual_effect :fade, :queue => {:position => ‘end’, :scope
=> ‘flash’}
end

I think the problem has to do with the fact that the form was not on the
original page, but was added dynamically. Does anyone know a way to
still use .rjs templates, even when the form was added dynamically?

  1. On an error, I refresh my form using:

     render :update do |page|
     	page.replace_html 'flash',
     	"<p style='color:red'>Errors occured when saving changes!</p>"
     	page[:flash].show
     	page[:flash].visual_effect :pulsate, :queue => {:position => 
    

‘end’, :scope => ‘flash’}
page[:flash].visual_effect :fade, :queue => {:position => ‘end’,
:scope => ‘flash’}

		page.replace_html 'scratchpad', :action => 'edit'
	end

The @item instance variable is passed to the error view, but <%=
error_messages_for(:item, :id => ‘ErrorExplanation’) %> in error.rhtml
does not show the errors (I’ve printed @item with the errors to the
server console, so I know they are there). Also the fields with errors
are no longer highlighted properly.

Any suggestions?

Thanks,

-Rich-


#2

Rich W. wrote:

		page.replace_html 'scratchpad', :action => 'edit'

This was the source of my problems. Apparently, when using ajax you can
only use render :partial or pass html code directly. I fixed this by
making a second copy of my edit view, _edit.rhtml, with no other
changes. That feels a bit inelegant, but it works.

I still can’t find a work-around for the first problem. Why do I need to
use “render :update do |page|” in my controller? I’d really like to move
all the updates to an .rjs template.

  1. When the user saves the changes, I want to put all the ajax changes
    in an RJS template. However, form_remote_tag :url =>{:action => ‘save’}
    does not appear to call the save.rjs template.

I can get the changes to fire by placing them in the save action itself,
using the following:

render :update do |page|
page[:scratchpad].hide
page.replace ‘todo’, :partial => ‘table’, :locals => {:items =>
items}
page[“row#{@item.id}”].visual_effect :highlight, :startcolor =>
#fff00’, :duration => 5
page.replace_html ‘flash’,

#{@item.title} successfully updated!

page[:flash].show
page[:flash].visual_effect :pulsate, :queue => {:position => ‘end’,
:scope => ‘flash’}
page[:flash].visual_effect :fade, :queue => {:position => ‘end’, :scope
=> ‘flash’}
end

I think the problem has to do with the fact that the form was not on the
original page, but was added dynamically. Does anyone know a way to
still use .rjs templates, even when the form was added dynamically?


#3

I still can’t find a work-around for the first problem. Why do I need to
use “render :update do |page|” in my controller? I’d really like to move
all the updates to an .rjs template.

I’ve noted that, when using a .rjs template, I must set the response
content_type to ‘text/javascript’ (otherwise the response is
‘text/html’).
I use rails 1.1.2

render(:template => ‘your_template’, :layout => false, :content_type
=> ‘text/javascript’)

Simo
Addsw.it


#4

Putting rjs in the controller is a new way.
It used to be only .rjs templates.

But its nice to put it in the controller for
updates and you kan skip the template.

def do_stuff
@data = some_stuff
render :update do |page|
page.replace_html ‘new’, @data
end
end

So you see straight away whats happening.
You wont have to lookup youre .rjs template
to see whats happening with the code.
Very nice.

2cents


#5

Thanks, but I’m a little confused. I was under the impression that Rails
would automatically call an .rjs file with a name matching the action in
question.

e.g. an AJAX helper calls my item.save() action. Once the action returns
item/views/save.rjs should be called automatically.

This worked for my initial test cases (where the Ajax helpers are part
of the view), but doesn’t work when the Ajax helpers are themselves
dynamically added.

-Rich-

Simo AddSW wrote:

I still can’t find a work-around for the first problem. Why do I need to
use “render :update do |page|” in my controller? I’d really like to move
all the updates to an .rjs template.

I’ve noted that, when using a .rjs template, I must set the response
content_type to ‘text/javascript’ (otherwise the response is
‘text/html’).
I use rails 1.1.2

render(:template => ‘your_template’, :layout => false, :content_type
=> ‘text/javascript’)

Simo
Addsw.it


#6

I’ve noted that, when using a .rjs template, I must set the response
content_type to ‘text/javascript’ (otherwise the response is
‘text/html’).

render(:template => ‘your_template’, :layout => false, :content_type
=> ‘text/javascript’)

Sorry, I’ve found that this is only due to a :before_filter I’ve used to
set uft-8 charset (in my applcation.rb: @headers[‘Content-Type’] =
“text/html; charset=‘utf-8’” )
Simo
Addsw.it


#7

Rich,

Move your code back to the rjs template and monitor the
development.log with tail -f log/development.log

Then install the FireBug browser extension for Firefox. FireBug will
let you monitor the responses being returned by Rails to your browser
for every Ajax call.

If you populate the variable “items” within the controller and have
the same RJS code within an RJS template then the following call would
be trying to access the controller’s local variable “items” which is
not in scope:

page.replace ‘todo’, :partial => ‘table’, :locals => {:items =>
items}

You could fix that by using @items

On 5/2/06, Rich W. removed_email_address@domain.invalid wrote:

-Rich-


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails


Cody F.
http://www.codyfauser.com


#8

Simo AddSW wrote:

render(:template => ‘your_template’, :layout => false, :content_type
=> ‘text/javascript’)

Actually, this doesn’t work either.

Here’s what I’m trying to do. When the user views the item list, there
is an Ajaxed edit button at the end of the list. If the user clicks that
button, an edit form is displayed below the list. This form is, itself,
Ajax enabled. Clicking submit changes the list, then hides the form.

I think I’m running into trouble because the Ajax form does not exist
when the page is first displayed. So the form’s Ajax helpers are not
able to set up something properly.

Everything works fine as long as I call render :update in the
controller. But I would really like to maintain the separation between
the controller and view, and put the view-modification commands back in
an .rjs template.

Thanks again,

-Rich-