【问题标题】:How to access ruby instance variable in Javascript through HAML template如何通过 HAML 模板访问 Javascript 中的 ruby​​ 实例变量
【发布时间】:2020-09-05 18:37:30
【问题描述】:

我有一个部分正在使用 CommentsController 呈现。让我们将此部分称为 _edit_comment.html.haml,我将在其中传递实例变量 @comment。

$("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: @comment.story, comment: @comment }) }')

在我的部分中,我有 JS,我想在单击按钮时调用它。

= form_with model: [story.industry, story, comment], class: "w-100" do |f|
  %fieldset.w-100                                    
    = f.text_area :content, rows: 2, hide_label: true, class: 'px-2 py-1', placeholder: "Leave a comment" 
  %fieldset  
    = f.submit "Update", class: 'btn submit text-white mt-2'   
    %span.btn.cancel.text-white.mt-2 Cancel-
:javascript
  $(document).ready( function() {
    $('.cancel').click(e => {
      console.log("#{@comment}")       
    })
  } );

我知道“#{}”适用于字符串,但我希望能够访问整个对象。目前,控制台的结果将是

#<Comment:0x000055971a9c5278>

我需要获取整个 ruby​​ 对象,因为我想将它作为变量传递给另一个将要渲染的部分。像这样的:

:javascript
  $(document).ready( function() {
    $('.cancel').click(e => {
      $("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: "#{@comment}".story, comment: "#{@comment}" }) }')
    })
  } );

这可能吗?

【问题讨论】:

    标签: javascript ruby-on-rails haml ujs


    【解决方案1】:

    要了解为什么您不能直接执行您正在尝试执行的操作,考虑一下页面呈现过程会有所帮助。当您的CommentsController 控制器呈现视图时,Rails 会处理您的 HAML 模板,其中包括处理所有嵌入的 Ruby(如字符串插值)。不过,在那之后,您的 HTML 只是 HTML,而您的 Javascript 也只是 Javascript。

    因此,在您的情况下,Rails 在渲染时插入 "#{@comment}",但是当 Javascript 在您的浏览器中执行时它只是一个字符串,但您不能传递 Ruby 对象等。同样,escape_javascriptrender 是 Rails 视图助手,所以当像这样直接插入 Javascript 时它们将无法工作。正如@BKSpureon 给出的那样,一个不错的选择是在原始页面中呈现编辑部分,然后只需使用一些普通的 JS 来显示/隐藏它。

    另一种选择是将您的按钮更改为远程(即 AJAX)link_to,然后将您的 Javascript 放入 JS 视图中。我并没有真正使用 HAML,但我认为链接类似于:

    = link_to 'Cancel', edit_comment_path(@comment), remote: true 
    

    edit_comment.js.haml中:

    :plain
    $("#edit-comment-#{object.id}").html('#{ escape_javascript(render :partial => 'edit_comment', locals: { story: "#{@comment}".story, comment: "#{@comment}" }) }')
    

    (一个快速的谷歌表明,更高版本的 HAML 可能不需要 :plain 包装器;如果不太正确,也许有 HAML 经验的人可以纠正这个问题。)

    【讨论】:

    • 非常感谢您详细解释页面渲染过程!是的,我使用了您和@bkspureon 建议的第二个选项,它工作正常。我希望我可以将你的两个答案都标记为答案,但我只能选择一个,所以我选择了较早的一个,但我也给了你一个赞成票!感谢您的指导:-)
    【解决方案2】:

    考虑使用嵌套形式...或类似的变体

    这里是 Rails 指南的链接:https://guides.rubyonrails.org/form_helpers.html#nested-forms

    看起来您想要一个嵌套表单,并且想要编辑 cmets,使用的表单与您想要编辑故事 (?) 或故事行业 (?) 时使用的表单相同。如果是这种情况,那么也许可以使用嵌套表单进行调查。

    其次,需要注意的另一个问题是:您不能将一个 HTML 表单放在另一个 HTML 表单中:这是做不到的。因此,您提出的 javascript 工作流程必须将编辑评论部分呈现在您上面的表单之外............或者您可以混合使用 javascript 并使用上面使用 jquery/javascript 的嵌套表单方法。 Ryan Bates 为这个主题贡献了两个优秀的 rails 演员——他们是 (1)(2)

    但要回答你的问题:

    ...不能那样做

    我不知道您是否真的可以按照您最初尝试的方式进行操作 - 传递复杂的 ruby​​ 对象

    ...但有解决办法:

    (A) 渲染部分并根据需要隐藏

    为什么不尝试不同的方法:直接在您的 html 中呈现部分内容(但将其隐藏起来不被用户看到)。

    单击按钮时,您可以简单地切换已存在部分的可见性。

    由于您使用的是 jQuery:

    (B) 异步获取部分

    您可以在事件处理程序中通过请求获取部分内容 - 刺激 js 非常适合这种类型的工作流程。您可以使用 fetch API 来获取 html 部分,或者如果您想支持 Internet Explorer 等,您可以使用 AJAX。

    ...........您必须决定是要嵌套表单,还是对完全独立的表单感到满意。

    【讨论】:

    • 感谢您的帮助!我会在不久的将来看看嵌套表单,但现在我通过使用链接到控制器等的 remote="true" 选择了选项 B。因为您的答案是第一个,我会将您的答案标记为答案: -)
    • @Nigel 如果您使用选项 B,请记住将部分放在原始表单之外。
    猜你喜欢
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    相关资源
    最近更新 更多