【问题标题】:Rails 6 + UJS: make ajax call on blur without jQueryRails 6 + UJS:在没有 jQuery 的情况下对模糊进行 ajax 调用
【发布时间】:2020-07-17 10:27:04
【问题描述】:

我有一个带有两个输入文本字段的表单。当第一个字段有值时,需要填充第二个字段的数据列表。我的一切都按我的意愿工作,除了我不知道如何在第一个字段失去焦点时触发 ajax 调用(我已经输入了一个链接,我可以单击以测试其他所有工作是否正常。)

org.rb

class Org < ApplicationRecord
  has_many: competitions
end

_form.html.haml

  .field
    = f.label "Competition:"
    League:
      = text_field_tag :org, @match.org&.name, list: "orgs", size: 60 # onblur: ?
    Division:
      = text_field_tag :competition, @match.competition&.name, list: "comps", size: 30

  %datalist#orgs
    = options_for_select Org.all.map(&:name).sort

  %datalist#comps
    = render "comps"

_comps.html.haml

= options_for_select @comps.map(&:name).sort

控制器

  def comps
    org = Org.find_from_identifier(params[:org])
    @comps = org&.competitions || []
    respond_to do |format|
      format.js
    end
  end

comps.js.erb

comps = document.getElementById("comps")
comps.innerHTML = "<%= j render "comps" %>"

如果我将此行放入表单中,当我单击它时,一切都会按预期工作:

= link_to 'test', update_comps_path(org: 'scottishfootballleague'), remote: true

(Routes.rb 中有get 'matches/comps', to: "matches#comps", as: :update_comps。)

所以我的问题是,当第一个输入字段失去焦点时,我该如何执行该链接的操作?

我尝试将onblur: 'updateComps()' 放入字段并使用

:javascript
  function updateComps() {
    var org = document.getElementById("org").value
    fetch("/matches/comps?org=" + org )
  }

这在某种意义上是有效的,即在正确的时间进行调用,但我缺少data-remote: true 附加到链接以使其成为在 rails 世界中有效的 ajax 调用的任何魔法。我是否缺少 Rails 助手?还是我需要指示 fetch() 如何处理返回的 js?

编辑:据我所知,对 fetch 的响应由我期望的 javascript 组成,并且可能需要执行。我试过这个:

:javascript
  function updateComps() {
    var org = document.getElementById("org").value
    fetch("/matches/comps?org=" + org,
      { credentials: "include"  })
    .then(response => {
      eval(response.text());
    })
  }

这有两个问题。 1) 它不起作用 2) 这看起来不太像 Rails。

更新(有答案)

我让 fetch 方法工作并执行服务器生成的 js:

function updateComps() {
    var org = document.getElementById("org").value
    fetch("/matches/comps.js?org=" + org,
      { credentials: "include"  })
    .then(response => response.text())
    .then(text => {
      eval(text)
    })
  }

我仍然不确定这样做的“Rails 方式”是什么。根据某些github discussions,Rails.ajax() 似乎已被删除(或仅在“内部”可用)。

【问题讨论】:

    标签: ruby-on-rails ajax ujs


    【解决方案1】:

    最简单的技巧是隐藏(display:none)您的测试链接并在第一个字段的blur 上触发click

    <script>
      var firstField = document.getElementById("id-of-first-filed");
      firstField.addEventListener("blur", updateComps);
    
      function updateComps(){
        document.getElementById("id-of-test-link").click();
      }
    </script>
    

    Rails 的做法是用户 Rails.ajax,所以你的 updateComps 看起来像。

    function updateComps() {
      var org = document.getElementById("org").value
    
      Rails.ajax({
        url: "/matches/comps.html?org=" + org,
        data: { credentials: "include" }
      })
    }
    

    控制器和js模板的其余代码将被重用。

    【讨论】:

    • 谢谢阿米特。使用 Rails.ajax() 我得到Uncaught ReferenceError: Rails is not defined。我的 application.js 中有import Rails from '@rails/ujs'。我错过了什么?
    【解决方案2】:

    在 app/assets/javascripts/appliction.js 中

    // This is a manifest file that'll be compiled into application.js, which will include all the files
    // listed below.
    //
    // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
    // vendor/assets/javascripts directory can be referenced here using a relative path.
    //
    // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
    // compiled file. JavaScript code in this file should be added after the last require_* statement.
    //
    // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
    // about supported directives.
    //
    //= require rails-ujs
    //= require activestorage
    //= require_tree .
    

    然后代替Rails.ajax

    使用$.ajax

    【讨论】:

    • 呃,看起来像 jQuery?
    猜你喜欢
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多