Problem calling an .rjs template using redirect_to

I've written an .rjs template to update more than one page element at once. It seems to work perfectly when I call it using a link on the page, i.e.:

  link_to_remote( image_tag("button_add.gif"), :url =>{:action => 'side_comment_return', :id => i, :article_id => @article.id } )

But when I attempt to call that same .rjs template from an action that responds to a form post, i.e.:

  def create_side_comment     Article.find(params[:id]).comments.create(params[:comment])     flash[:notice] = "Added comment."     redirect_to (:action => 'side_comment_return', :id => params[:paragraph_id], :article_id => params[:id] )   end

it spews all of the javascript onto the area of the page that i am trying to update, rather than simply rendering the html like I expect, like:

try { Element.update("side_comment3", "\ntest -test

\n"); Element.update("add_comment_button3", "\"Add"); } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('Element.update(\"side_comment3\", \"\ntest -test

\n\");\nElement.update(\"add_comment_button3\", \"\\"Add\");'); throw e }

Am I using the redirect_to method inappropriately? Thanks for any help, this is the first time I've posted a question here, and I appreciate your time.

Hi Dave, (?)

Basically, you're mixing apples and oranges. Short answer is, you need to use the RJS version of redirect_to.

def create_side_comment    Article.find(params[:id]).comments.create(params[:comment])    flash[:notice] = "Added comment."    render :update do |page|       page.redirect_to (same_args)    end end

hth, Bill

Thanks for your help, Bill. It seems this hasn't solved my problem, though... when I try what you have written, rather than updating the appropriate elements on the page, the browser window redirects to a new page, the content being the javascript generated by the .rjs template. Is page.redirect_to not the method I'm looking for?

Thanks again, Dave

Hi Dave,

yowzadave wrote:

Thanks for your help, Bill. It seems this hasn't solved my problem, though...

Then no thanks are expected :wink:

when I try what you have written, rather than updating the appropriate elements on the page, the browser window redirects to a new page, the content being the javascript generated by the .rjs template.

The core of your current difficulty may be rooted (my first ones were) in not fully groking that a Rails app is truly an application: one that lives, except for help from session data, for exactly one request-response cycle. Rails looks at what's requested and does its best to return that. The POST request that invoked the method named create_side_comment told Rails to return html. The RJS template will generate javascript that gets pushed to the browser - by Rails, which has been told to return whatever it returns as html.

Is page.redirect_to not the method I'm looking for?

It would probably help to see the rjs template you've been talking about. Along with an explanation of what it is you're trying to do in this new case. The first, as stated, is a correct use of RJS templates.

Best regards, Bill

Ok, here's the idea:

There are a number of paragraphs in an "article," and the user has the option to click a link next to each paragraph, to add a comment to that paragraph. That link calls the .rjs action/template i've called "side_comment," with the controller looking like this:

  def side_comment     @paragraph_id = params[:id]     @article_id = params[:article_id]   end

and the .rjs template looking like this:

page.replace_html "side_comment#{@paragraph_id}", :partial => 'side_comment_form'

page.replace_html( "add_comment_button#{@paragraph_id}",                   link_to_remote ( image_tag('button_minus.gif',                           :alt => 'Return to comments view',                           :title => 'Return to comments view'),                           :url => {:action => 'side_comment_return',                             :id => @paragraph_id,                             :article_id => @article_id }) )

So when the user clicks the button, it updates a div next to that paragraph with a form asking for the various elements of the comment, and also changes the button to a different state (from a plus to a minus). If the user clicks this button again, it calls the .rjs action/template "side_comment_return," which switches the element containing the form back to its original state, and also changes the button back to its original state. This seems to be working correctly.

The problem is, when the user completes and submits the form, I would like both the element with the form and "add_comment_button" to switch back to the initial view. So I thought I'd use the same action, "side_comment_return", that I am using in the previously described case. The .rjs for that action looks like this:

page.replace_html( "side_comment#{@paragraph_id}", :partial => 'list_side_comments' )

page.replace_html( "add_comment_button#{@paragraph_id}",                   link_to_remote( image_tag('button_add.gif',                   :alt => 'Add comment to this paragraph',                   :title => 'Add comment to this paragraph'),                   :url => {:action => 'side_comment',                     :id => @paragraph_id,                     :article_id => @article_id } ) )

So my thinking was, the method "create_side_comment" that my comment form invoked could just redirect to the "side_comment_return" method when it was finished...but I haven't yet been able to get this working, as described earlier. Anyhow, I hope this clarifies what I'm trying to do.

Cheers, Dave

Hi Dave,

Sorry for my delay in replying.

yowzadave wrote: <snip>

So when the user clicks the button, it updates a div next to that paragraph with a form [...]

<snip>

The problem is, when the user completes and submits the form [...]

And sorry I didn't pick up on this sooner. Given the symptom you're describing (i.e., getting html displayed when you want js executed) I'd guess the problem's coming from your form. That is, your form submission is telling the server it's expecting a response that's html to display, not js to execute. If you're not already using it, switch to form_remote_tag and let us know if the problem persists.

hth, Bill

Bill:

I'm already using form_remote_tag; the whole _side_comment_form partial I'm using looks like this:

<%= form_remote_tag(:update => "side_comment#{@paragraph_id}",                     :url => { :action => "create_side_comment", :id => @article_id, :paragraph_id => @paragraph_id } ) %>   <label for="comment_author">Name:</label><br />   <%= text_field 'comment', 'author' %><br /> <label for="comment_body">Comment:</label><br />   <%= text_area 'comment', 'body', :cols => "40", :rows => "5" %>   <%= submit_tag "Post Comment" %> <%= end_form_tag %>

In fact, I've already been able to get the form to update correctly in place on the page by simply bypassing the .rjs template and putting

redirect_to (:action => 'list_side_comments', :paragraph_id => params[:paragraph_id], :article_id => params[:id] )

at the end of the create_side_comment def in the controller. Unfortunately, this doesn't allow me to update the other element on the page at the same time, as I'd hoped to do by using .rjs...

Thanks again, Dave

yowzadave wrote:

Bill:

I'm already using form_remote_tag; the whole _side_comment_form partial I'm using looks like this:

<%= form_remote_tag(:update => "side_comment#{@paragraph_id}",                     :url => { :action => "create_side_comment", :id => @article_id, :paragraph_id => @paragraph_id } ) %>   <label for="comment_author">Name:</label><br />   <%= text_field 'comment', 'author' %><br /> <label for="comment_body">Comment:</label><br />   <%= text_area 'comment', 'body', :cols => "40", :rows => "5" %>   <%= submit_tag "Post Comment" %> <%= end_form_tag %>

In fact, I've already been able to get the form to update correctly in place on the page by simply bypassing the .rjs template and putting

redirect_to (:action => 'list_side_comments', :paragraph_id => params[:paragraph_id], :article_id => params[:id] )

at the end of the create_side_comment def in the controller. Unfortunately, this doesn't allow me to update the other element on the page at the same time, as I'd hoped to do by using .rjs...

Thanks again, Dave

>

Hey Bill

Try removing the :update option from your form_remote_tag. If you're using RJS this isn't necessary and in my experience spews the returned RJS code into the specified element. The example link_to_remote you gave for example omitted the :update parameter and thus acted as was to be expected.

try:

<%= form_remote_tag(:url => { :action => "create_side_comment",                     :id => @article_id,                     :paragraph_id => @paragraph_id } ) %>

#controller

def create_side_comment   @article_id = params[:id]   @paragraph_id = params[:paragraph_id]

  Article.find(@article_id).comments.create(params[:comment])

  flash[:notice] = "added comment"   render(:action => "side_comment_return") end

I rarely use rjs templates, preferring to do the one or two lines I make use of in-line with render(:update).

In case something doesn't work, the idea here is that the normal action takes place, then it renders the 'side_comment_return' action's rjs template (as all that needs is @article_id and @paragraph_id: both present in the current action). No redirect is necessary.

Cheery-o Gustav Paul

Gustav Paul

Try removing the :update option from your form_remote_tag.

Paul is exactly right. The :update option should not be used if you're trying to update multiple DOM elements. That's what rjs is for. Very common misunderstanding.

If you're using RJS this isn't necessary and in my experience spews the returned RJS code into the specified element. The example link_to_remote you gave for example omitted the :update parameter and thus acted as was to be expected.

Best regards, Bill

> Try removing the :update option from > your form_remote_tag.

This worked perfectly. Thanks for your help, guys, and sorry I wasn't able to point you to the offending code earlier. I appreciate your time a lot,

Dave Anderson