[Help] How to render or replace a partial page having <script> tag?


#1

My problem is quite complicated.

In my project, I have to use static

  • However, the section above is not static, I have to write a
    helper to dynamically generate it. so it becomes to

    1. <%= generate_tree_view(:id=>1) ## this will generate the
    section and insert them in the page 2.
    But, right now, my problem is I have to call this tree view page by ajax like this 1. ## view file show.erb.html 2. ... 3. <%= link_to_remote 'see_tree', :url=>{:action=>'view_tree', :id=>1} > 4.
    5. ... 1. ## controller file tree_controller.rb 2. ... 3. def view_tree 4. ### get some parameters, say 'tree_parameter' array 5. render :update do |page| 6. page.replace_html 'view_tree', :partial=>'view_tree', :object=>tree_parameter 7. end 8. end 9. ... 1. ## partial page _view_tree.erb.html 2. <%= generate_tree_view(:tree_parameter=>view_tree) 3.
    I thought this should work because it actually worked if I directly use the generate_tree_view help in the show.erb.html. But however, when the partial page is called by ajax, the section which is generated by generate_tree_view didn't show up in the page. The final page only shows this: 1. ## view file show.erb.html, saw by firebug 'cause it is the only way I can see a rendered page. 2. ... 3.
    4.
    5.
    6. ... It seems they got executed by the javascript call instead of just display it. So, what should I do if I just want to inject a section in a rendered page. I'm not sure whether you have already got my idea, but I really appreciate it if you help me solve this problem. Thank you.

    #2

    I don’t use RJS although I have used rails to generate javascript
    dynamically. I tend to prefer to see the javascript that’s being
    executed so that when things go wrong I know exactly why. Anyway,
    someone else reading this thread might have a quick answer whereas I
    don’t, but …

    On Oct 25, 3:53 pm, boblu removed_email_address@domain.invalid wrote:

    1. get some parameters, say ‘tree_parameter’ array

    2. render :update do |page|

    3. page.replace_html
      

    ‘view_tree’, :partial=>‘view_tree’, :object=>tree_parameter
    7. end
    8. end
    9. …

    1. partial page _view_tree.erb.html

    2. <%= generate_tree_view(:tree_parameter=>view_tree)

    There are no quotes around ‘view_tree’ above. Is that right?

    Check the javascript console (ctrl+shift+J in firefox) for javascript
    errors that your function may be making.

    Instead of RJS you could just try rendering the partial (that’s just
    my preference - it might be easier to see what’s going wrong).
    render :partial => ‘view_tree’ ,
    :locals => { :your_var => ‘your val’ … }
    (_view_tree.html.erb)
    And in your link_to_remote, I think you’ll need to include an :update
    option with the id of the element whose inner html you are updating.
    See the docs
    http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html

    Any script tag in the partial will probably be eval’d by the
    javascript interpreter. (The link_to_remote should generate an
    Ajax.Updater with the evalScripts:true option which you can check for
    just to make sure).

  • It seems they got executed by the javascript call instead of just
    display it.

    So, what should I do if I just want to inject a section in a
    rendered page.

    Prototype will remove script tags whether it is set to process them or
    not so you will likely not see them in firebug after the update (which
    is probably a good thing). (I’m referring specifically to prototype’s
    Ajax.Updater)

    Also check your output in your functional tests for this controller:

    Check the partial _element3_1.html.erb.

    def test_1a
    xml_http_request :post,‘view_tree’,params
    assert_tag :tag => ‘script’ , :content => /alert/
    end


    Daniel B.


    #3

    On Oct 25, 5:53 am, boblu removed_email_address@domain.invalid wrote:

    My problem is quite complicated.
    3. def view_tree
    4. ### get some parameters, say ‘tree_parameter’ array
    5. render :update do |page|
    6. page.replace_html
    ‘view_tree’, :partial=>‘view_tree’, :object=>tree_parameter
    7. end
    8. end

    page.replace_html maps onto prototype’s Element.update function which
    strips script tags from what it’s inserting (and due to the way it
    does the update I doubt it would make much difference if the scripts
    weren’t removed).

    Two ways out:
    a) Use link_to_remote ‘Click me’, :update => ‘view_tree’, :url =>
    {…}
    and then in your controller instead of using render :update just
    render the partial

    b) call that javascript from the render :update block ie

    render :update do |page|
    page.replace_html
    ‘view_tree’, :partial=>‘view_tree’, :object=>tree_parameter
    page << "alert(‘hello world’)
    end

    whether you do this before or after the replace_html somewhat depends
    on whether the JS depends on the page having being updated or not

    Fred


    #4

    On Oct 25, 4:56 pm, boblu removed_email_address@domain.invalid wrote:

    @Fred
    Thank you for reply. I just tried the two ways you suggested.

    1. use link_to_remote :update in view and render :partial in
      controller instead of calling render :update
      This really does not make any differences. They gave the same output
      which all my staff in tag got stripped.

    It may strip it, but the javascript definitely runs (at least in my
    simple test app).

    in the view.

    the stuff inside the render :update block is not evaluated within the
    context of the controller. You can call helper functions in there such
    as remote_fuction or generate_tree_view.

    Fred


    #5

    @Fred

    I re-checked the script code I generated and found some problem there.
    After fixing that problem, everything goes beautifully by using you
    method.
    Thank you very much for your suggestion.

    And I really feel this is the most helpful place when I have some
    questions with rails.
    Cheers!

    On Oct 26, 2:41 am, Frederick C. removed_email_address@domain.invalid


    #6

    @Fred
    Thank you for reply. I just tried the two ways you suggested.

    1. use link_to_remote :update in view and render :partial in
      controller instead of calling render :update
      This really does not make any differences. They gave the same output
      which all my staff in tag got stripped.

    2. directly insert the javascript in the controller.
      Actually, this is not allowed in my case.
      Because I generated a bunch of quite complicated javascript in the
      ‘generate_tree_view’ helper.
      And inside this helper, I also called ‘remote_function’ to give a
      javascript call to some link which will be rendered as a tree’s node
      by the library I am using.
      As the remote_function can not be called in the controller, I can not
      generate the script inside controller.
      And the only way I can generate it is put ‘generate_tree_view’ helper
      in the view.

    @Daniel
    Thank you for reply. Though I barely understand what your point is.
    As far as I understood, if you want to make a ajax call in rails by
    using link_to_remote,
    you either use ‘link_to_remote :update’ in view and use
    ‘render :partial’ in controller
    or use ‘link_to_remote’(without update field) in view and use ‘render
    page.replace’ in controller.

    But you said ‘Prototype will remove script tags whether it is set to
    process them or
    not’.
    Does that mean I actually can not insert a dynamic tag inside
    the rendered page by using prototype javascript call?


    #7

    On Oct 26, 2:56 am, boblu removed_email_address@domain.invalid wrote:

    @Fred

    @Daniel
    Thank you for reply. Though I barely understand what your point is.
    As far as I understood, if you want to make a ajax call in rails by
    using link_to_remote,
    you either use ‘link_to_remote :update’ in view and use
    ‘render :partial’ in controller
    or use ‘link_to_remote’(without update field) in view and use ‘render
    page.replace’ in controller.

    I was suggesting you try ‘link_to_remote :update’ as doing it a
    different
    way might help you to work out what the bug is.
    Ignore my point on RJS though - I’ve just got “helper-method” fatigue
    at the moment; comes from wanting to know and control what’s
    going on under the covers all the time.

    But you said ‘Prototype will remove script tags whether it is set to
    process them or
    not’.
    Does that mean I actually can not insert a dynamic tag inside
    the rendered page by using prototype javascript call?

    I think you can insert script tags if you really wanted to. Maybe
    with prototype’s Ajax.Request
    where you grab the response and inject it into the dom using your own
    handler.
    In firefox it will show up like a tag with a text node so not what you
    want unless you set it not to display. Just inserting it into the dom
    may not get the javascript interpreter to execute it.
    You might have to eval the contents of the script tag.
    Much easier just to use Ajax.Updater with evalScripts:true.


    Daniel B.