Whenever I need either multiple updates, or conditional updates from AJAX events, I find myself doing this sort of thing: (I''ve left out all the conditional stuff that would decide which template to use.) which_action = ''some_ajax_template_thing'' result_string = render_to_string(:partial => ''js_escape'', :object => render_to_string(:action => which_action, :layout => false)) result_string = "$(''element_name'').innerHTML = ''#{result_string}''" render(:text => result_string, :layout => false) The ''js_escape'' partial is just a one-liner: <%= escape_javascript(js_escape) %> ..which works around the fact that escape_javascript() isn''t available to controllers. The view then does something like: :update => ''eval(request.responseText)'' Is there a better way to do this, or is this roughly as nasty as it usually looks? Thanks, --Wilson.
When I have more complex logic to deal with, especially when multiple things need to be updated, I use one of two different strategies: 1) use HTTP headers to help carry the load. This works great if (for example) you want to know the id of an object that was just created, or the element to insert some new element before, or whatever. Just set a header with the id and grab it on the client: -- controller code -- def myaction ... headers[''X-New-Id''] = @object.id render :partial => "object" end -- javascript code -- function onComplete(request) { var id = request.getResponseHeader(''X-New-Id'') new Effect.Highlight(''something_'' + id) } -- template -- <%= link_to_remote "update me!", :url => { :action => "myaction" }, :update => "somediv", :complete => "onComplete(request)" %> 2) You can partition the body of the response and have the client parse and process it as needed. Used in conjunction with the headers, this can be a great way to update multiple elements in a single go, although you have to do things a bit more manually (you can''t use the :update directive in link_to_remote, for instance). Javascript code: function onComplete(request) { var body = request.getResponseText() var parts = body.split("-------------") $(''first'').innerHTML = parts[0] $(''second'').innerHTML = parts[1] $(''third'').innerHTML = parts[2] // etc... } Hopefully I didn''t completely misunderstand your question, and this applies in some way to what you posted. :) - Jamis On Jul 30, 2005, at 5:02 PM, Wilson wrote:> Whenever I need either multiple updates, or conditional updates > from AJAX events, I find myself doing this sort of thing: (I''ve > left out all the conditional stuff that would decide which template > to use.) > > which_action = ''some_ajax_template_thing'' > result_string = render_to_string(:partial => ''js_escape'', :object > => render_to_string(:action => which_action, :layout => false)) > > result_string = "$(''element_name'').innerHTML = ''#{result_string}''" > render(:text => result_string, :layout => false) > > The ''js_escape'' partial is just a one-liner: > <%= escape_javascript(js_escape) %> > ..which works around the fact that escape_javascript() isn''t > available to controllers. > > The view then does something like: :update => ''eval > (request.responseText)'' > > Is there a better way to do this, or is this roughly as nasty as it > usually looks? > > Thanks, > --Wilson. > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
While that isn''t directly drop-in applicable to what I was doing today, it''s still really helpful. Thanks. When you need to send back a decent chunk of ''dynamic'' HTML content, how do you go about escaping the special characters in it? As you can see in my code snippet, I had to go as far as actually passing a render() to another render().. That seemed really clumsy. Jamis Buck wrote:> When I have more complex logic to deal with, especially when multiple > things need to be updated, I use one of two different strategies: > > 1) use HTTP headers to help carry the load. This works great if (for > example) you want to know the id of an object that was just created, or > the element to insert some new element before, or whatever. Just set a > header with the id and grab it on the client: > > -- controller code -- > def myaction > ... > headers[''X-New-Id''] = @object.id > render :partial => "object" > end > > -- javascript code -- > function onComplete(request) { > var id = request.getResponseHeader(''X-New-Id'') > new Effect.Highlight(''something_'' + id) > } > > -- template -- > <%= link_to_remote "update me!", > :url => { :action => "myaction" }, > :update => "somediv", > :complete => "onComplete(request)" %> > > 2) You can partition the body of the response and have the client parse > and process it as needed. Used in conjunction with the headers, this > can be a great way to update multiple elements in a single go, although > you have to do things a bit more manually (you can''t use the :update > directive in link_to_remote, for instance). Javascript code: > > function onComplete(request) { > var body = request.getResponseText() > var parts = body.split("-------------") > $(''first'').innerHTML = parts[0] > $(''second'').innerHTML = parts[1] > $(''third'').innerHTML = parts[2] > // etc... > } > > Hopefully I didn''t completely misunderstand your question, and this > applies in some way to what you posted. :) > > - Jamis > > On Jul 30, 2005, at 5:02 PM, Wilson wrote: > >> Whenever I need either multiple updates, or conditional updates from >> AJAX events, I find myself doing this sort of thing: (I''ve left out >> all the conditional stuff that would decide which template to use.) >> >> which_action = ''some_ajax_template_thing'' >> result_string = render_to_string(:partial => ''js_escape'', :object => >> render_to_string(:action => which_action, :layout => false)) >> >> result_string = "$(''element_name'').innerHTML = ''#{result_string}''" >> render(:text => result_string, :layout => false) >> >> The ''js_escape'' partial is just a one-liner: >> <%= escape_javascript(js_escape) %> >> ..which works around the fact that escape_javascript() isn''t >> available to controllers. >> >> The view then does something like: :update => ''eval >> (request.responseText)'' >> >> Is there a better way to do this, or is this roughly as nasty as it >> usually looks? >> >> Thanks, >> --Wilson.
On Jul 30, 2005, at 6:55 PM, Wilson wrote:> While that isn''t directly drop-in applicable to what I was doing > today, it''s still really helpful. Thanks. > > When you need to send back a decent chunk of ''dynamic'' HTML > content, how do you go about escaping the special characters in it? > As you can see in my code snippet, I had to go as far as actually > passing a render() to another render().. That seemed really clumsy.Looks like I did miss the point, then. :) If all you''re after is escaping the javascript: which_action = ''some_ajax_template_thing'' result_string = render_to_string(:action => which_action, :layout => false) template = "$(''element_name'').innerHTML = ''<%= escape_javascript (javascript) %>''" render(:inline => template, :locals => { :javascript => result_string }) - Jamis> > Jamis Buck wrote: > >> When I have more complex logic to deal with, especially when >> multiple things need to be updated, I use one of two different >> strategies: >> 1) use HTTP headers to help carry the load. This works great if >> (for example) you want to know the id of an object that was just >> created, or the element to insert some new element before, or >> whatever. Just set a header with the id and grab it on the client: >> -- controller code -- >> def myaction >> ... >> headers[''X-New-Id''] = @object.id >> render :partial => "object" >> end >> -- javascript code -- >> function onComplete(request) { >> var id = request.getResponseHeader(''X-New-Id'') >> new Effect.Highlight(''something_'' + id) >> } >> -- template -- >> <%= link_to_remote "update me!", >> :url => { :action => "myaction" }, >> :update => "somediv", >> :complete => "onComplete(request)" %> >> 2) You can partition the body of the response and have the client >> parse and process it as needed. Used in conjunction with the >> headers, this can be a great way to update multiple elements in a >> single go, although you have to do things a bit more manually >> (you can''t use the :update directive in link_to_remote, for >> instance). Javascript code: >> function onComplete(request) { >> var body = request.getResponseText() >> var parts = body.split("-------------") >> $(''first'').innerHTML = parts[0] >> $(''second'').innerHTML = parts[1] >> $(''third'').innerHTML = parts[2] >> // etc... >> } >> Hopefully I didn''t completely misunderstand your question, and >> this applies in some way to what you posted. :) >> - Jamis >> On Jul 30, 2005, at 5:02 PM, Wilson wrote: >> >>> Whenever I need either multiple updates, or conditional updates >>> from AJAX events, I find myself doing this sort of thing: (I''ve >>> left out all the conditional stuff that would decide which >>> template to use.) >>> >>> which_action = ''some_ajax_template_thing'' >>> result_string = render_to_string(:partial => >>> ''js_escape'', :object => render_to_string(:action => >>> which_action, :layout => false)) >>> >>> result_string = "$(''element_name'').innerHTML = ''#{result_string}''" >>> render(:text => result_string, :layout => false) >>> >>> The ''js_escape'' partial is just a one-liner: >>> <%= escape_javascript(js_escape) %> >>> ..which works around the fact that escape_javascript() isn''t >>> available to controllers. >>> >>> The view then does something like: :update => ''eval >>> (request.responseText)'' >>> >>> Is there a better way to do this, or is this roughly as nasty as >>> it usually looks? >>> >>> Thanks, >>> --Wilson. >>> > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Aarrgh.. This is one of those answers that should have been so obvious, that I wish the Internet would forget I ever asked. Nice. Jamis Buck wrote:> On Jul 30, 2005, at 6:55 PM, Wilson wrote: > >> While that isn''t directly drop-in applicable to what I was doing >> today, it''s still really helpful. Thanks. >> >> When you need to send back a decent chunk of ''dynamic'' HTML content, >> how do you go about escaping the special characters in it? >> As you can see in my code snippet, I had to go as far as actually >> passing a render() to another render().. That seemed really clumsy. > > > Looks like I did miss the point, then. :) If all you''re after is > escaping the javascript: > > which_action = ''some_ajax_template_thing'' > result_string = render_to_string(:action => which_action, :layout => > false) > > template = "$(''element_name'').innerHTML = ''<%= escape_javascript > (javascript) %>''" > render(:inline => template, :locals => { :javascript => result_string }) > > - Jamis > >> >> Jamis Buck wrote: >> >>> When I have more complex logic to deal with, especially when >>> multiple things need to be updated, I use one of two different >>> strategies: >>> 1) use HTTP headers to help carry the load. This works great if >>> (for example) you want to know the id of an object that was just >>> created, or the element to insert some new element before, or >>> whatever. Just set a header with the id and grab it on the client: >>> -- controller code -- >>> def myaction >>> ... >>> headers[''X-New-Id''] = @object.id >>> render :partial => "object" >>> end >>> -- javascript code -- >>> function onComplete(request) { >>> var id = request.getResponseHeader(''X-New-Id'') >>> new Effect.Highlight(''something_'' + id) >>> } >>> -- template -- >>> <%= link_to_remote "update me!", >>> :url => { :action => "myaction" }, >>> :update => "somediv", >>> :complete => "onComplete(request)" %> >>> 2) You can partition the body of the response and have the client >>> parse and process it as needed. Used in conjunction with the >>> headers, this can be a great way to update multiple elements in a >>> single go, although you have to do things a bit more manually (you >>> can''t use the :update directive in link_to_remote, for instance). >>> Javascript code: >>> function onComplete(request) { >>> var body = request.getResponseText() >>> var parts = body.split("-------------") >>> $(''first'').innerHTML = parts[0] >>> $(''second'').innerHTML = parts[1] >>> $(''third'').innerHTML = parts[2] >>> // etc... >>> } >>> Hopefully I didn''t completely misunderstand your question, and this >>> applies in some way to what you posted. :) >>> - Jamis >>> On Jul 30, 2005, at 5:02 PM, Wilson wrote: >>> >>>> Whenever I need either multiple updates, or conditional updates >>>> from AJAX events, I find myself doing this sort of thing: (I''ve >>>> left out all the conditional stuff that would decide which >>>> template to use.) >>>> >>>> which_action = ''some_ajax_template_thing'' >>>> result_string = render_to_string(:partial => ''js_escape'', :object >>>> => render_to_string(:action => which_action, :layout => false)) >>>> >>>> result_string = "$(''element_name'').innerHTML = ''#{result_string}''" >>>> render(:text => result_string, :layout => false) >>>> >>>> The ''js_escape'' partial is just a one-liner: >>>> <%= escape_javascript(js_escape) %> >>>> ..which works around the fact that escape_javascript() isn''t >>>> available to controllers. >>>> >>>> The view then does something like: :update => ''eval >>>> (request.responseText)'' >>>> >>>> Is there a better way to do this, or is this roughly as nasty as >>>> it usually looks? >>>> >>>> Thanks, >>>> --Wilson. >>>>