The type ahead functionality works where it is supposed to. The issue though is that the type ahead functionality is making the JSON request on every request for the data when it should really only happen for one specific request.
I have the following controller:
#controllers/agencies_controller.rb
class AgenciesController < ApplicationController
def get_unique_agency_names
@unique_agency_names = Agency.uniq.pluck(:name)
respond_to do |format|
format.json { render json: @unique_agency_names }
end
end
...
end
I have the following in my javascript file:
#app/assets/javascripts.agencies/index.js
$(document).ready(function(){
/* For typeahead functionality on name input of search form for agencies */
var agency_names = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: '../agencies/get_unique_agency_names.json'
});
$('#prefetch .typeahead.name_input').typeahead(null, {
name: 'agency_names',
source: agency_names
});
});
And just for completion, here is the one place where I want this functionality to happen: In this form:
# just showing the relevant part of the form
<div class="form-group" id="prefetch">
<%= f.label :name_cont, "Agency Name" %>
<%= f.text_field :name_cont, class: "form-control typeahead name_input", placeholder: "Enter Agency Name" %>
</div>
Here is my relevant route in config/routes.rb
resources :agencies do
collection do
get 'get_unique_agency_names'
end
end
My specific question is: How can I ensure that the GET "/agencies/get_unique_agency_names"
is only called when it is supposed to? Right now it is appending this JSON request for every request. I only want the JSON request to happen for one specific request.
Twitter's Type Ahead Examples
I think you need this
$('#prefetch .typeahead.name_input').typeahead(null, {
generateOnLoad:false,
name: 'agency_names',
source: agency_names
});
generateOnLoad {boolean}
null (default)
If enabled, the source data will be generated (doing Ajax request and preparing to data to be searched) on page load instead of waiting for the input to be focused.
PN:This option does not work well with dynamic: true unless some other configuration is adjusted.
Also, If you find the rails manifest file adds your call to every page just check element exists before type ahead is bound:
if($('#prefetch .typeahead.name_input').length){
$('#prefetch .typeahead.name_input').typeahead(null, {
generateOnLoad:false,
name: 'agency_names',
source: agency_names
});
}
I would suggest a strategy for “limiting” requests, rather than programmatically enforcing a single request, as it seems you are dealing with a large data set. You can set Bloodhound’s prefetch
option to cache what you can, and the sufficient
and remote
options to ensure that requests for your JSON file are back-filled and rate-limited. Set a higher value for Typeahead’s minLength
option as a last line of defense.
Prefetch will serve you to a degree, as it depends on the browser’s local storage for caching, which has limited capacity. If your data set is large, it will only cache a portion, and further requests will be required after initialization.
Remote handles requests after initialization, and can debounce or throttle these requests for you, thereby reducing the number of requests made. See the url
, rateLimitBy
, and rateLimitWait
options, which can be assigned to remote
as a hash. Further, Bloodhound will use remote
to back-fill additional datums if your sufficient datum count is not reached.
Finally, don’t pass null
and set the minLength
option to something higher than the default of 1
on your Typeahead constructor. This will prevent overly abundant lookups on your dataset. Just be sure that the minLength
value is shorter than the length of your smallest, possible result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With