0

Driving me crazy because it should be so easy!!!

    // file: /app/javascript/packs/application.js
    require("jquery")
    require("custom/sites_manage")

    // file: /app/javascript/custom/sites_manage.js
    console.log(">>> this file is being loaded")
    function testFunc() {
      return "asdf"
    }

When I spin up a local server and go to the home page, in the console I do see >>> this file is being loaded great! But then when I call testFunc() I get: Uncaught ReferenceError: testFunc is not defined

Why??? I don't think I'm doing anything different than the numerous answers/tutorials on this topic (e.g., this one, or this one)

james
  • 3,989
  • 8
  • 47
  • 102
  • How and where are you calling the `testFunc()`? And how are you adding the js file in your htmls? – Victor Feb 23 '20 at 21:25
  • Hi, I answered with partial info. Check if the js file is inside an iframe. If so, please, can you add more info? – user1039663 Feb 23 '20 at 21:27
  • @Victor calling `testFunc()` from browser console just as a test. It is loaded into html because it should be compiled in the `packs/application.js` and then on application layout there's a `javascript_pack_tag 'applicaton'` – james Feb 23 '20 at 21:49

2 Answers2

0

This problem can be from two causes:

Firstone: the js file is loading into the current iframe, but on a inaccesible context. Solution: just under the definition of testFunc add a line with window.publicTestFunc = testFunc; like this:

function testFunc() {
  return "asdf";
}
window.publicTestFunc = testFunc;

If the problem is because of contexts, now you should be able to call publicTestFunc from outside the context.

Second cause: the js file is being loaded on an iframe. In this case solve the problem is a bit more complicated and messaging between iframes with ondata events, or using the iframe url hash is the only available communication mechanism... so usually is always a better idea to find why is this happening (I need more information if this is the case).

Edit: there are a possible third cause: the js file is loaded as a webworker... webworkers also have isolated contexts. The communication situation is similar to the iframe scenario.

However, probably the cause is the firstone and with the window.publicfunction = privatefunction you should be able to call your function.

user1039663
  • 1,230
  • 1
  • 9
  • 15
  • ok so this is working, but it's ludicrous to have to assign proper context to EVERY single custom defined function and variable???!!!! is that really the way webpack is supposed to work? that would make it so much more cumbersome over the old asset pipeline that's insane... – james Feb 23 '20 at 21:56
  • Only the public ones, also after answering you i saw the Victor answer and I remembered that export functions can be used also. However, if the window.functionname approach seems complicated for you, the export approach is even more complicated. – user1039663 Feb 23 '20 at 22:00
  • Also, know that there is a reason behind these exporting things both with window.function or export function: to discern the public methods from the private ones, like object oriented programming... and it would help you to keep more organized your code because you would think twice about using all the stuff in the webpack from outside. So it will help you to isolate your code, and in long-term this will make the code easier to maintain, in theory. – user1039663 Feb 23 '20 at 22:03
  • I mean... yes i get that. I would naturally wrap things up in modules anyway. It's just... this ruins the speed of a 'fast build' where you're just trying to quickly deploy something and have a small tiny `testFunc`. I liked that before I had the option of doing it this way, without being forced to now wrap up my random things in a `miscellaneousFunctions` IIFE or something like that – james Feb 23 '20 at 22:17
  • You can also use this syntax: window.functionname = function(args) { ... }; – user1039663 Feb 24 '20 at 00:43
0

As you're using webpack, you need to export your function in order to allow other files to access it:

function testFunc() {
  return "asdf"
}
export default testFunc;

And to use it:

import testFunc from '../path/to/custom/sites_manage.js'
testFunc()
Victor
  • 5,043
  • 3
  • 41
  • 55
  • I'm not entirely sure where to put the import line so that `testFunc()` is accessible inside the browser console? Also.... what on earth is the purpose of webpack then. It's crazy to have to export EVERY function like this???? It's way worse than the old asset pipeline?? Can't I just import an entire file and everything inside of it somehow? – james Feb 23 '20 at 21:59