7stud

7stud

What do I have to do to use JQuery in a Phoenix app? Suppose I create my Phoenix app like this:

/phoenix_apps% mix new --umbrella a_umbrella
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating apps
* creating config
* creating config/config.exs

Your umbrella project was created successfully.
Inside your project, you will find an apps/ directory
where you can create and host many apps:

    cd a_umbrella
    cd apps
    mix new my_app

Commands like "mix compile" and "mix test" when executed
in the umbrella project root will automatically run
for each application in the apps/ directory.


~/phoenix_apps% cd a_umbrella/apps
~/phoenix_apps/a_umbrella/apps% mix new my_app --sup
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/my_app.ex
* creating lib/my_app/application.ex
* creating test
* creating test/test_helper.exs
* creating test/my_app_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd my_app
    mix test

Run "mix help" for more commands.

That gives me this directory structure:

~/phoenix_apps/a_umbrella% tree .
~/phoenix_apps/a_umbrella% tree .
.
├── README.md
├── apps
│   └── my_app
│       ├── README.md
│       ├── lib
│       │   ├── my_app
│       │   │   └── application.ex
│       │   └── my_app.ex
│       ├── mix.exs
│       └── test
│           ├── my_app_test.exs
│           └── test_helper.exs
├── config
│   └── config.exs
└── mix.exs

6 directories, 9 files

What do I need to do to use JQuery in a template?

Showing Posts 19 to 10

7stud

7stud OP

I couldn’t get jQuery to work. Thanks for your help.

03juan

03juan

That’s a very good question. This style is a side effect only type of import that should run the script’s global code. :thinking:

Maybe try to compile it separately in the esbuild args string and import it as a separate asset in the HTML head, and skip the extra step through app.js?

Or just straight-up inline the jquery_setup.js code in app.js?

7stud

7stud OP

Hurray! Clap, clap! I got all the methods you suggested to work. Somebody understands scope in javascript!

Out of curiosity, why didn’t my attempts with JQuery work? I clicked the link:

Download the uncompressed, development jQuery 3.6.4

and I copied the code and put it in ..assets/vendor/jquery.js.

In ../assets/js/jquery_setup.js, I have:

import jQuery from "../vendor/jquery"
window.jQuery = jQuery
window.$ = jQuery

And, in app.js I have:

import "./jquery_setup.js"

But, in my browser I get an error in the js console that says $ isn’t recognized. I looked through the jQuery code, and I don’t think it exports “jQuery” or “$”. If it would take too much time to figure out, don’t bother.

03juan

03juan

This will import hello into the scope of app.js, but will not make it available to the HTML document automatically unless you assign the function to the global window element.

// file: assets/js/app.js
import {hello} from "../vendor/my_functions.js" 
window.hello = hello

A good next step would be to namespace your exported functions, then assign that to the global element:

// file: assets/vendor/my_functions.js
export function hello () {...}
export function etc () {...}

// file: assets/js/app.js
import * as MyFunctions from "../vendor/my_functions.js" 
window.MyFunctions = MyFunctions

// in HTML <script>
window.onload = function () {
  MyFunctions.hello()
  MyFunctions.etc()
}

This can start to get unwieldy when you have a lot of functionality in multiple HTML scripts.

I would instead move them to app.js and set up your code from there:

// file: assets/js/app.js
import * as MyFunctions from "../vendor/my_functions.js" 

window.onload = function () {
    MyFunctions.hello()
}

// now this is only necessary if you also want to access them directly from the dev console
window.MyFunctions = MyFunctions

Lastly, if app.js also gets too large for your liking, or you only want to have certain features running in specific pages, you can move the relevant code to its own module, have esbuild compile it separately, then load it into your page.

// file: assets/js/my_feature.js
import { hello } from  "../vendor/my_functions.js" 

button = document.querySelector("#someButton")
button.addEventListener("click", () => { hello() }

add js/my_feature.js to the esbuild args string (and restart the server to apply changes to config files)

# file: config/config.exs
config :esbuild,
  version: "0.17.11",
  default: [
    args:
      ~w(js/app.js js/my_feature.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]
<!--- my_page.html.heex or inside render/function component ~H template -->
<script defer phx-track-static type="text/javascript" src={~p"/assets/my_feature.js"}>
</script>

<button id="someButton" type="button">Run hello()</button>
Exadra37

Exadra37

I also highly recommend Elixir in action, but PragDave is the only one that spends the time to make your mind shift from OOP to FP and thats why I always recommend his book first.

Another excellent book is Real-Time Phoenix by @sb8244:

7stud

7stud OP

% elixir --version
Erlang/OTP 24 [erts-12.3.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

Elixir 1.14.4 (compiled with Erlang/OTP 24)

I’m using Phoenix 1.7.2, which I installed a few days ago with the command:

$ mix archive.install hex phx_new

mix.exs:

defmodule MyWeb.MixProject do
  use Mix.Project

  def project do
    [
      app: :my_web,
      version: "0.1.0",
      build_path: "../../_build",
      config_path: "../../config/config.exs",
      deps_path: "../../deps",
      lockfile: "../../mix.lock",
      elixir: "~> 1.14",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()
    ]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [
      mod: {MyWeb.Application, []},
      extra_applications: [:logger, :runtime_tools]
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
      {:phoenix, "~> 1.7.2"},
      {:phoenix_html, "~> 3.3"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:phoenix_live_view, "~> 0.18.16"},
      {:floki, ">= 0.30.0", only: :test},
      {:phoenix_live_dashboard, "~> 0.7.2"},
      {:esbuild, "~> 0.7", runtime: Mix.env() == :dev},
      {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev},
      {:telemetry_metrics, "~> 0.6"},
      {:telemetry_poller, "~> 1.0"},
      {:gettext, "~> 0.20"},
      {:jason, "~> 1.2"},
      {:plug_cowboy, "~> 2.5"}
    ]
  end

  # Aliases are shortcuts or tasks specific to the current project.
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    [
      setup: ["deps.get", "assets.setup", "assets.build"],
      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
      "assets.build": ["tailwind default", "esbuild default"],
      "assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]
    ]
  end
end

I’ll try adding my js file to a non umbrella project and see if I get different results.

codeanpeace

codeanpeace

Does your umbrella project happen to be created using an older version of the Phoenix generators?

7stud

7stud OP

I purchased “Elixir in Action” using a discount code on this forum. I’ve read part of it. It is very good. At the same time, I purchased “Phoenix in Action”, and I’m revisiting it now.

7stud

7stud OP

For me one of the best courses and book that made me switch my brain from Object Orientated Programming to Functional Programming.

I spent a few years learning erlang before elixir.

I’ve already read it.

7stud

7stud OP

I tried creating a js module, but it doesn’t work for me. Here’s what I tried:

../assets/vendor/my_functions.js


export function hello() {
  alert("My javacript functions got imported!")
};

../assets/js/app.js

import {hello} from "../vendor/my_functions.js"  

Without the braces around hello, I got the following error:

No matching export in "vendor/my_functions.js" for import "default"

    js/app.js:21:7:
      21 │ import hello from "../vendor/my_functions.js"
         ╵        ~~~~~

Template:

<section>
  <div id="fade_target">Hello world, from Demo!</div>
</section>
<script>
  window.onload = function() {
      hello()
  } 
</script>

Error in the javascript console in my browser:

ReferenceError: Can’t find variable: hello

which points here:

            <section>
                <div id="fade_target">Hello world, from Demo!</div>
            </section>
            <script>
            window.onload = function() {
                hello()   <===============================
            }
            </script>

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews