JS Interoperability

For a better development experience, you can configure Surface to automatically load JS hooks related to your components when a colocated .hooks.js file is provided.

This section assumes you already have basic knowledge of using JS hooks with LiveView. In case you don't, please read JavaScript interoperability for general guidance.

Usage

Create a colocated .hooks.js file with the same base name of the component.

Example:

my_app_web/components
├── ...
├── card.ex
├── card.hooks.js

Export your hook as default in card.hooks.js:

export default {
  mounted(){
    console.log("Card mounted")
  }
}

Use the :hook directive to bind the hook to the HTML element:

<div id="my_div" :hook>
  ...
</div>

Hooks require a unique ID on each element.

Defining multiple hooks

If you need to bind more than one hook to different elements in you HTML, you can export multiple hooks:

let Card = {
  mounted(){
    console.log("Card mounted")
  }
};

let OtherHook = {
  mounted(){
    console.log("OtherHook mounted")
  }
};

export {Card, OtherHook};

Then use the :hook directive passing the name of each hook related to each element:

<div :hook="Card">
  ...
  <div :hook="OtherHook">
</div>

You can also access hooks defined by other components using the :from option:

<div :hook={"Card", from: MyComponents.CardList}>
  ...
</div>

Choosing a different output dir

By default, Surface builds all components' JS files into ./assets/js/_hooks/. If you need the compiler use a different folder, you can set the hooks_output_dir configuration in your config/dev.exs. Example:

config :surface, :compiler, hooks_output_dir: "assets/js/surface"