What's new

Rails 6 + UJS: make ajax call on blur without jQuery

Fever

Active member
Staff member
I have a form with two input text fields. The datalist for the second field needs to be populated when the first field has a value. I have everything working as I want except I can't work out how to fire the ajax call when the first field loses focus (I have put in a link I can click to test everything else is working.)

org.rb

class Org < ApplicationRecord
has_many: competitions
end


_form.html.haml

.field
= f.label "Competition:"
League:
= text_field_tag :eek:rg, @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


controller

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


comps.js.erb

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


If I put this line into the form everything works as I expect when I click it:

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


(Routes.rb has get 'matches/comps', to: "matches#comps", as: :update_comps in it.)

So my question is how do I do what that link does when the first input field loses focus?

I tried putting onblur: 'updateComps()' into the field and using

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


This works in the sense that the call gets made at the right time but I'm missing whatever magic data-remote: true attaches to the link to make it an ajax call that works in the rails world. Am I missing a Rails helper? Or do I need to instruct fetch() with what to do with the js that gets returned?

Edit: I've got as far as working out that the response to the fetch consists of the javascript I expect, and which presumably needs to be executed. I've tried this:

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


There are two problems with this. 1) it doesn't work 2) this doesn't seem very rails-like.

Update (with an answer)

I got the fetch approach working and executing the server generated 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)
})
}


I'm still not at all sure what the "Rails way" of doing this is. Rails.ajax() seems to have been removed (or is only available 'internally') according to some github discussions.

Continue reading...
 
Top