Functions in app.js wont fire

I have a simple js function in app.js

   function myFunction() {
    document.getElementById("demo").innerHTML = "Hello World";
}

When I add the function to the script tag in the template it works.
in app.js I get undefined in the browser console.
What am I missing ?

1 Like

This app.js does a perfectly good job of gutting the default page as rendered by Phoenix:

// Brunch automatically concatenates all files in your
// watched paths. Those paths can be configured at
// config.paths.watched in "brunch-config.js".
//
// However, those files will only be executed if
// explicitly imported. The only exception are files
// in vendor, which are never wrapped in imports and
// therefore are always executed.

// Import dependencies
//
// If you no longer want to use a dependency, remember
// to also remove its path from "config.paths.watched".
import "phoenix_html";

// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"

(function() {
  function myFunction(){
    document.querySelector(".container").innerHTML = "Hello World";
  }

  myFunction();
}());

I suspect that your problem relates to the fact that the JavaScript handled by Brunch is “modularized” which code placed directly in the page isn’t.

A 10 minute primer to JavaScript modules, module formats, module loaders and module bundlers

You can breach the encapsulation of the module by attaching the function to the global object window (not a recommended practice):

// Brunch automatically concatenates all files in your
// watched paths. Those paths can be configured at
// config.paths.watched in "brunch-config.js".
//
// However, those files will only be executed if
// explicitly imported. The only exception are files
// in vendor, which are never wrapped in imports and
// therefore are always executed.

// Import dependencies
//
// If you no longer want to use a dependency, remember
// to also remove its path from "config.paths.watched".
import "phoenix_html";

// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"

window.myFunction = function myFunction () {
  document.querySelector(".container").innerHTML = "Hello World";
};

From the browser console:

> window.myFunction();
  undefined

The browser page changes - undefined in this case merely states that the function didn’t return a value.

See also How are Phoenix javascript assets callable from the browser console?.

Another way is to make Brunch attach the exports to the global object for you (still not recommended - but at least exports are being used rather attaching to the global object directly):

// Brunch automatically concatenates all files in your
// watched paths. Those paths can be configured at
// config.paths.watched in "brunch-config.js".
//
// However, those files will only be executed if
// explicitly imported. The only exception are files
// in vendor, which are never wrapped in imports and
// therefore are always executed.

// Import dependencies
//
// If you no longer want to use a dependency, remember
// to also remove its path from "config.paths.watched".
import "phoenix_html";

// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"

export function myFunction () {
  document.querySelector(".container").innerHTML = "Hello World";
}

and then in the brunch-config.js:

  npm: {
    enabled: true,
    globals: {myApp: 'js/app'}
  }

so in the browser console:

> window.myApp.myFunction();
  undefined

ECMAScript 6 modules: the final syntax

5 Likes

Thank you so much for the response! You`re a life saver.
I managed to do the following in app.js

document.querySelector('#arf').addEventListener('click', myFunction);

and it works like a charm!

2 Likes