I was wondering if it’s possible to move the function from inside script tag into the app.js inside the assets directory and have the html execute the onlick function of the JS from the assets directory.
If it is possible, what are the necessary steps to achieve this goal?
that’s kinda the thing. I have no idea how to start. I tried reading online about the solution to start but JS interoperability is quite confusing for me.
I was hoping to get a solution for this question, so I might be able to understand how a custom JS can interact with phoenix liveview.
Instead of reaching for something like alpine, you should instead be looking into Hooks. Basically the issue you’re having is that the onclick handler is being registered the first time that you load the page but when the page updates it is cleared. To solve this you need a hook to basically add the onclick behaviour every time that the dom element changes. You can read more about this here: JavaScript interoperability — Phoenix LiveView v0.15.4
I heard using hooks would be the solution to my problem but the thing is, getting it to actually work is quite confusing for me. I was wondering if it’s possible for someone to demonstrate how it would work using the example that I have. It would clarify the necessary steps required to solve this problem.
What I’ve done:
I’ve added hooks into let liveSocket let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, ...})
Created a hook callback object
let Hooks = {}
Hooks.searchHandler() {
mounted() {
let Input = element.parentElement.getElementsByTagName("input")[0];
Input.classList.toggle("w-0");
}
}
I know this is horribly wrong but this is my understand from read the documents and reading other sources online. I’m really new at this and I need an example of this solution.
So you’re actually really close which is why I had asked earlier what you had tried. So what you are missing here is that the hook is supposed to be an object, not a function as you have currently declared it. This object has several lifecycle hooks it can implement, as well as some properties automatically available to it. You declare this hook object like so
let Hooks = {}
Hooks.SearchHandler = {
mounted() {
// Code to run when the dom element is mounted
}
}
so as you can see it’s pretty close to what you had. Then, in your markup you only need to pass the name of the hook, not call it as you attempted to do. So the full markup would look like
Here you can see that we have access to this.el which refers to the element that you registered the hook on. If you check the docs you can see the full list of attributes as well as callbacks you can use. This should be enough to replicate the functionality you had previously. I have not tested it, but it should get you started at least.
I really appreciate your time in viewing my issue.
It still doesn’t seem to work for me. Right now I’m not sure if I’m doing something wrong or I’m missing something but following the steps you’ve provided should make things easier.
Okay, I’m happy to try and help you some more but I’ll need more information than “it doesn’t work”. What are you seeing? If you add some console log statements to the hook, are they called? Is it called when you expect it to be called? Steps like these will help us help you, but it will also help you to see what’s going on.
I have no idea how to verify what the problem is, that’s why I replied with “it doesn’t work”. I don’t know whether or not I’m missing something or I did something wrong. Besides these three changes, I haven’t touched anything.
You have not declared the hooks object correctly based on the code that you shared here. You need to create an object and assign it to the key SearchHandler in the Hooks object. Like so:
As for verifying what went wrong in the future, as I suggested you can add some log statements to make sure that the code is being run. If you added a log call to the mounted function and it didn’t print you can be sure that the mounted function is never called. Then you can work on figuring out why it’s not running.
as for using console.log to debug the function; it seems like the mount is not being called or even recognized at all. Literally has nothing in the console log.
Yeah by that I meant just literally before this line, like so
console.log('app.js is running')
let Hooks = {}
I also just reread the docs and noticed that you need a unique ID on the element which has the hook. So just a normal HTML ID attribute which must be unique on the page.