ruby-on-rails - ujs + remotipaart - 运行 jQuery `.html(...)` 调用时,附加的 html 变为文本

标签 ruby-on-rails remotipart

我正在使用 Rails 5,带有 remotipart。远程部分版本是:

gem 'remotipart', github: 'mshibuya/remotipart'

(在提出这个问题时,当前提交是 88d9a7d55bde66acb6cf3a3c6036a5a1fc991d5e)。

当我想提交具有 multipart: true 和 remote: true` 的表单但不发送任何附加文件时,效果很好。但是当我发送文件时,它失败了。

为了说明这种情况,请考虑如下响应:

(function() {
  modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n  <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n    <span aria-hidden>\n      &times;\n    <\/span>\n  <\/div>\n  Code can\'t be blank\n<\/div>\n');
}).call(this);

当这个响应被执行时,在到达后立即(因为它是js),表单看起来就像它预期的那样(在这种情况下,这个验证错误是正确的发生,并且呈现的危险警报是正确的出现这样的文本):

enter image description here

但是,当我填写文件字段并重复完全相同的情况(完全相同的验证错误)时,表单看起来完全不同:

enter image description here

如果您能猜到,内容将以文本形式传递。从服务器收到的实际响应有点不同:

<script type="text/javascript">try{window.parent.document;}catch(err){document.domain=document.domain;}</script>(function() {
  modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n  <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n    <span aria-hidden>\n      &times;\n    <\/span>\n  <\/div>\n  Code can\'t be blank\n<\/div>\n');
}).call(this);

这是我响应的实际正文(这不是一个糟糕的复制粘贴,而是由 remotipart 包装的实际响应)。

modalErrors 函数非常愚蠢:

function modalErrors(html) {
    $('#main-modal > .modal-dialog > .modal-content > .modal-body > .errors').html(html);
}

比较 jQuery 附加的 html block (我在浏览器的 DOM 检查器中查找它们),它们看起来像这样:

好:

<div class="alert alert-danger" role="alert">
  <ul style="list-style-type: none">
    <li>Code can't be blank</li>
  </ul>
</div>

坏:

Code can't be blank

我在这里缺少什么?我想要的是允许我的回复在需要时附加 html 内容。

最佳答案

remotipart lib 使用名为 iframe-transport 的内容,稍后解开内容并执行响应,就像使用 ajax 获取一样。

但是,标签会从响应中删除,因此响应将转换为如下内容:

try{window.parent.document;}catch(err){document.domain=document.domain;}(function() {
  modelErrors('\n  \n    \n      &times;\n    \n  \n  Code can\'t be blank\n\n');
}).call(this);

我发现以合理的方式与该库交互的解决方案是定义另一个辅助助手,类似于 j/escape_javascript:

module ApplicationHelper

  JS_ESCAPE_MAP = {
      '\\'   => '\\\\',
      '<'    => '\\u003c',
      '&'    => '\\u0026',
      '>'    => '\\u003e',
      "\r\n" => '\n',
      "\n"   => '\n',
      "\r"   => '\n',
      '"'    => '\\u0022',
      "'"    => "\\u0027"
  }

  JS_ESCAPE_MAP["\342\200\250".force_encoding(Encoding::UTF_8).encode!] = '&#x2028;'
  JS_ESCAPE_MAP["\342\200\251".force_encoding(Encoding::UTF_8).encode!] = '&#x2029;'

  def escape_javascript_with_inside_html(javascript)
    if javascript
      result = javascript.gsub(/(\\|\r\n|\342\200\250|\342\200\251|[\n\r<>&"'])/u) {|match| JS_ESCAPE_MAP[match] }
      javascript.html_safe? ? result.html_safe : result
    else
      ''
    end
  end

  alias_method :jh, :escape_javascript_with_inside_html

end

在容易被常规 ajax 和 remotipart 发送的 View 中 - 在不同的场景中,我的意思是 - 只需将 j 调用替换为 jh 调用即可。示例:

modalErrors('<%= j render 'shared/model_errors_alert', instance: @team %>')

被替换为

modalErrors('<%= jh render 'shared/model_errors_alert', instance: @team %>')

关于ruby-on-rails - ujs + remotipaart - 运行 jQuery `.html(...)` 调用时,附加的 html 变为文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39374113/

相关文章:

jquery - 使用 jQuery 和 Rails 3 实现 ajax 可排序列表

jquery - 在 Rails 中加载表单后调用 JavaScript 函数

ruby-on-rails - Shopify 和 Rails : Webhook being fired multiple times

mysql - 在 Rails 3 中同时使用 postgresql 和 mysql?

jquery - Rails 4 不使用 Remotipart 远程提交表单

jquery - Rails escape_javascript 和 remotipart

ruby-on-rails - 仅针对特定 Controller 调用before_filter

ruby-on-rails - 使用 Rails 5 和 Carrierwave 远程上传图像

html - 使用 remotipart 提交带有文件输入的表单包装一个文本区域以响应