Rails 7: Stimulus Not showing output in console - javascript

I am a rookie and I was trying to learn about how to use Stimulus online and then suddenly
my console does not show output(in inspect element) when I use Stimulus in rails app
app/javascript/controllers/dropdown_controller.js
import { Controller } from "#hotwired/stimulus"
// Connects to data-controller="dropdown"
export default class extends Controller {
connect() {
console.log("Hello")
}
}
app/javascript/aplication.js
// Entry point for the build script in your package.json
import "#hotwired/turbo-rails"
import "./controllers"
app/views/orders/_form.html.erb
<div data-controller="dropdown">
<h3>Hello</h3>
</div>
(I didn't display the whole form because this is the main context in the form which is related to Stimulus) So what is the problem here? Why is it not showing output in the console(inspect element in chrome)
According to other Stackoverflow posts, we had to run rails assets:clobber in order to fix it but mine still does not work :(
Any Chance I am doing something dumb?

Related

Elixir Phoenix serve Javascript from /priv/static

I am currently fighting esbuild in my phoenix project. I have a heex template on which I want to use Trumbowyg as a text editor. First I tried to import the javascript file via vendoring it and doing import trumbowyg from '../vendor/trumbowyg.min.js in app.js.
I thought this would work because it did for AlpineJs. But it didn't. It complained about missing jQuery. So I vendored jQuery the same way: import {jQuery, $} from '../vendor/jquery.min.js. But no success. Same error message Uncaught ReferenceError: $ is not defined.
Then I had the idea to fix it via importing the scripts in the template withing <script> tags. SO i just threw the two js files into the /priv/static/assets/ folder. This worked in development with the following tags:
<script type="text/javascript" src={Routes.static_path(#conn, "/assets/jquery.min.js")}></script>
<script type="text/javascript" src={Routes.static_path(#conn, "/assets/trumbowyg.min.js")}></script>
But this stopped working in production (I use the docker deploy method). Then I tried using some kind of Plug.Static implementation but I did not get it to work.
So my question now is: How can I make those scripts load in a production environment? Even better would be to know how to configure esbuild to use deploy the script files correctly. I don't know what to change, because my AlpineJs import is working fine.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"
import Alpine from "../vendor/alpine.min"
window.Alpine = Alpine;
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
dom: {
onBeforeElUpdated(from, to) {
if (from._x_dataStack) {
window.Alpine.clone(from, to)
}
}
}
})
// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
// connect if there are any LiveViews on the page
liveSocket.connect()
// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket
That's the content of my app.js file. But like I said, adding: import trumbowyg from '../vendor/trumbowyg.min.js or import {jQuery, $} from '../vendor/jquery.min.js gets me errors like Uncaught ReferenceError: $ is not defined and Uncaught ReferenceError: jQuery is not defined.
Every help is appreciated. Thanks in advance.

Elixir Phoenix - How to create and import javascript files into specific templates

I'm currently experimenting with the Elixir Phoenix framework together with Liveview. For my project, I would like to write some Javascript code that is only imported on certain pages (templates). Although this seems like something very trivial, I am struggling to get it working.
At this moment I created a seperate Javascript file as such assets/js/custom.js. After doing this, I added the following line to my root.html.heex as a first test to see if this already works. For this line, I simply looked at how app.js is imported.
<script defer phx-track-static type="text/javascript" src={Routes.static_path(#conn, "/assets/custom.js")}></script>
The next step would then be to figure out how to import it in a seperate template instead of the root. However, this first test already failed resulting in the following error:
[debug] ** (Phoenix.Router.NoRouteError) no route found for GET /assets/custom.js (MyAppWeb.Router)
(my_app 0.1.0) lib/phoenix/router.ex:405: MyAppWeb.Router.call/2
(my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
(my_app 0.1.0) lib/plug/debugger.ex:136: MyAppWeb.Endpoint."call (overridable 3)"/2
(my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
(phoenix 1.6.15) lib/phoenix/endpoint/cowboy2_handler.ex:54: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Could somebody help me figure this one out? How does one add seperate Javascript files and only import them in specific templates?
You can import all your custom javascript once in app.js, assign them as hooks which you can then use in your (live) views, wherever needed, for example;
custom.js
export const SomeFunction = {
mounted() {
alert("some function ran!");
}
}
app.js snippet
...
import {SomeFunction} from "./custom.js"
let Hooks = {}
Hooks.SomeFunction = SomeFunction
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: Hooks})
...
Then in your live view render function (or template) add the hook
...
def render(assigns) do
~H"""
...
<div id="my-hook" phx-hook="SomeFunction"></div>
...
end
...
More about javascript interoperability can be found on the Phoenix hex page here. You can tie them to all sorts of phoenix events.
nb. Also note that #conn isn't available in live views, only #socket is.

How_To_Solve_ReactJS_Problem

Sorry for my bad english and a new learner programming.
I have a single problem with React.JS in App.js,
I have written an exterrnal JS file, called Fundamental.js, the code is the following:
const testing = () => {
console.log('test log 12456');
}
export default testing;
When I import Fundamental.js file into App.js, my VS Code shows a popup message:
'testing' is defined but never used.
how to solve it?
the import list in my React App.js is:
import logo from './Linux_Logo.png';
import './App.css';
import testing from './FundaMental';
Thank you so much to whoever solves my problem!
Welcome to SOF. In your component testing should be Testing [capitalized] and In testing nothing is returned that's why showing this in the terminal. Try this plz:
import React from 'react';
function Testing() {
return (
console.log('test log 12456');
)
}
export default Testing
when importing:
import Testing from './FundaMental';
It is better to keep the same name of the function name and the js file name.
VS Code is saying that you imported a function but you're not using it.
Your testing module defines the function testing. It doesn't execute it.
There are two ways to get rid of the warning:
Call the testing function in App.js, or
Don't import it into App.js.
If testing is the beginning of a React component then follow #Pabel Mahbub's answer, including the suggestion to rename the function Testing and rename the file Testing.js. As your app grows that will make it easier to manage.
This is only a warning/reminder that you import something but you never used it. React has this kind of checking that will warn us of the unusual code that we have. To fix this warning either trigger the function or remove it. Hope this helps!

Rails 7 Import Maps - import folder with custom scripts

playing around with Rails 7 and import maps. Trying to import a folder with some custom JS.
# config/importmap.rb
pin_all_from "app/javascript/custom", under: "custom"
# app/javascript/application.js
import "custom"
Gives Uncaught TypeError: Failed to resolve module specifier "custom" on Chrome
and Uncaught Error: Unable to resolve specifier 'custom' from [shim] on Firefox
interestingly import "custom/script" works fine.
what am I doing wrong?
I had this same problem and found the following solution:
# app/javascript/application.js
import "custom/my_custom_code.js"
This means that
pin_all_from "app/javascript/custom", under: "custom" is really just making each custom JS file available under the custom namespace. Therefore, you still need to import each file individually.
While this might still be a valid thing to do in some use cases, I think what I was trying to do was a bit of an anti-pattern in Rails 7.
It is very easy to use Stimulus controllers instead.
Stimulus Handbook For reference
For example, to dismiss an alert when a user clicks the "x"
// app/javascript/alerts_controller.js
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
dismiss () {
this.element.style.display = 'none';
}
}
<div data-controller="alerts">
<h2> Alert! </h2>
<span data-action="click->alerts#dismiss"><i class="fas fa-times"></i></span>
</div>

Custom Uppy Plugin

I'm trying to make a custom Uppy React plugin but I'm getting the following error
'TypeError: Cannot call a class as a function'
import Plugin from 'uppy/src/core/Plugin';
export default class DropZone extends Plugin {
}
I am then consuming the component as follows:
import React from 'react';
import Uppy from 'uppy/lib/core/Core';
import DropZone from '../DropZone';
const uppy = new Uppy({ debug: true });
uppy.run();
export default class FileManager extends React.Component {
render() {
return (<DropZone uppy={uppy} />);
}
}
I've cut down the code for simplicity. I looked at the implementation of the uppy DragDrop plugin and followed its implement but still get the same error.
Has anyone had experience writing a react plugin for Uppy? as I'm lost as to how I can resolve this error.
Thanks
I've successfully created a plugin using the following import statement:
import { Uppy, Plugin, PluginOptions, UppyFile } from "#uppy/core";
It's not clear from your question whether you're using the npm package or have downloaded manually, but in my case I installed Uppy using:
npm i #uppy/core
First of all, in your "DropZone" plugin, you'll need to implement at least the install() and uninstall() methods (those get called by uppy).
Second, if you want to tell uppy to use your plugin, you need to do something like:
const uppy =
new Uppy({ debug: true })
.use(DropZone)
.run();
I suggest simply looking at the source code for other plugins to understand how they work, there are different kinds of Plugins - Providers for files management, GUI plugins for display in the Dashboard, etc...
Hope this helps

Categories

Resources