1

I followed this tutorial but I'm running into an issue: https://gorails.com/episodes/global-autocomplete-search

I am getting an error in the js console when refresh the page: search.js:31 Uncaught TypeError: $input.easyAutocomplete is not a function

However, when I put create an options variable directly in the console and run: $input = $("[data-behavior='autocomplete']") and then $input.easyAutocomplete(options) it works fine. Any idea why I am able to run easyAutocomplete directly in the console but not in the normal course of my app? Here is my application.js file:

// Rails functionality
window.Rails = require("@rails/ujs")
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("trix")
require("@rails/actiontext")

require("jquery")
require("easy-autocomplete")

require("custom/show")
require("custom/search")

// Tailwind CSS
import "stylesheets/application"

// Stimulus controllers
import "controllers"

// Jumpstart Pro & other Functionality
import "src/actiontext"
import "src/confirm"
import "src/direct_uploads"
import "src/forms"
import "src/timezone"
import "src/tooltips"

import LocalTime from "local-time"
LocalTime.start()

// ADD YOUR JAVACSRIPT HERE

// Start Rails UJS
Rails.start()

Any ideas on this? Thanks!

Edit 1 - added search.js:

search.js

$(document).on('turbolinks:load', function() {
    if ($('#search-input').length) {
        console.log('in search.js')
        $input = $("[data-behavior='autocomplete']")

        var options = {
        getValue: "name",
        url: function(phrase) {
          return "/search.json?q=" + phrase;
        },
            categories: [
                {
                    listLocation: "entities",
                    header: "<strong>Entities</strong>"
                },
                {
                    listLocation: "tags",
                    header: "<strong>Tags</strong>"
                }
            ],
            list: {
                onChooseEvent: function() {
                    var url = $input.getSelectedItemData().url
            $input.val("")
            Turbolinks.visit(url)
                }
            }
        }

        $input.easyAutocomplete(options)
    }
})
jackerman09
  • 2,492
  • 5
  • 29
  • 46
  • It's related to the loading sequence. When you run in the console, everything is loaded, but when search.js is being loaded, it's probably not waiting for document.ready to attach the easyAutocomplete function. Without seeing search.js it's hard to say... are you waiting for document.ready? – Les Nightingill Jun 28 '20 at 19:24
  • @LesNightingill thanks, this was my suspicion as well. It is waiting for the Turbolinks:load event. I've added the code for search.js above. Any idea? – jackerman09 Jun 28 '20 at 23:46
  • looks like you're on the right debugging track. Now add a console.log or debugger statement to see if $input is defined when you think it is. Also you need to confirm that the easy-autocomplete javascript is loaded before search.js (yes, it appears that way in your application.js, but confirm anyway). Also could be a scoping issue, the autocomplete might be in a different scope. Dunno, just some things to try. – Les Nightingill Jun 29 '20 at 00:09
  • @LesNightingill Unfortunately no luck still. I put in the console.logs that you suggested and $input is defined correctly at the right times. This seems like it may be relevant, but I can't figure out how to implement it: https://github.com/pawelczak/EasyAutocomplete/issues/200 Any suggestions? My jquery.easy-autocomplete.js files already start with `var EasyAutocomplete = (function(scope){` and end with `})(jQuery);`, but I'm not sure if that's relevant. – jackerman09 Jul 02 '20 at 01:33
  • I'm just about out of ideas. But just one question to pursue... confirm that EasyAutocomplete variable is defined a) before the first line of search.js?, and also b) within the callback in search.js.? It should be. – Les Nightingill Jul 02 '20 at 03:04
  • Hmm, seems like it may not be. I stuck `console.log(easyAutocomplete)` at the very beginning of `search.js` and get this error when I refresh the page: search.js:1 Uncaught ReferenceError: easyAutocomplete is not defined at Object. (search.js:1) at Object../app/javascript/custom/search.js (search.js:33) at __webpack_require__ (bootstrap:19) at Module../app/javascript/packs/application.js (application.js:1) at __webpack_require__ (bootstrap:19) at Object.1 (log.js:56) at __webpack_require__ (bootstrap:19) at bootstrap:83 at bootstrap:83 – jackerman09 Jul 03 '20 at 16:39
  • @LesNightingill I even tried putting `search.js` in the `packs` folder and adding a separate `<%= javascript_pack_tag 'search' %>` at the bottom of `application.html.erb` and I'm still getting the same error. I'm totally lost here :/ – jackerman09 Jul 03 '20 at 16:50
  • wait... packs? I didn't see anything related to webpacker in your previous comments or question. I though you were just using sprockets (you showed application.js ... this is processed by sprockets). Did you intend to use webpacker or did it just show up uninvited? If you're intending to use just sprockets (this was implied in your question) then get rid of the webpacker compilation and javascript_pack_tag stuff. If you intend to use webpacker, then are you running webpack-dev-server? Please clarify your asset compilation intention (sprockets? webpacker? both?). – Les Nightingill Jul 03 '20 at 19:33
  • @LesNightingill Yes I am intentionally using Webpacker, sorry if that wasn't clear. I am using Rails 6 and afaik Webpacker is used by default. Yes, the webpack server is running and works with all other javascript in the app. As a test I moved the entire minified version of easy-autocomplete into the beginning of search.js (inside the turbolinks load function) and it actually works. – jackerman09 Jul 04 '20 at 03:00
  • So instead of actually copying easy-autocomplete into search.js you need to include it in the webpack style, with a require or import statement, whichever is appropriate for easy-autocomplete. – Les Nightingill Jul 04 '20 at 04:04

0 Answers0