DEV Community

Cover image for Understanding Hooks in the Phoenix Framework
Rushikesh Pandit
Rushikesh Pandit

Posted on

Understanding Hooks in the Phoenix Framework

Hello everyone,

I hope this message finds you in good spirits. In the current piece, we will focus our attention on the concept of hooks in the Phoneix app.

Phoenix Framework Hooks are a great extension of LiveView improvements by executing custom JavaScript on the client side. It enables you to use JavaScript directly, which isn’t feasible or efficient only with live view, where there is a need for dynamic behaviour.

In the Phoenix Framework context, hooks are simply a method that allows triggering JavaScript when a given element of the LiveView is rendered or updated in the DOM.

Hooks help in smoothly adding any form of interaction with the LiveView that is already painted on the browser. Most of the interaction with Phoenix LiveView is that the contents are rendered on the server side. However, there are cases such as when the UI is animated, or some other javascript library is turning up that some actions on the front end have to take place in real-time to perform certain actions on the user interface.

Importantly, while Phoenix LiveView efficiently handles state and UI updates from the server, there are cases when client-side code is required. For example:

  • Third-Party Libraries: Imagine you're integrating a charting library like Chart.js or a UI toolkit that requires client-side code to initialise after a LiveView page is loaded.

  • Custom DOM Manipulation: Sometimes, you need to apply JavaScript directly to an element after it's rendered.

  • Animations: There are cases where animations triggered by JavaScript can enhance the user experience, such as sliding in a notification bar or creating modal popups.

  • Handling Real-Time Events: For real-time event handling beyond what Phoenix Channels or LiveView directly provide, you may need JavaScript to react to specific events in the front end.

With the introduction of Hooks, it has become possible to enhance client-side functionalities without losing the merits of server-side rendered pages.

Adding Support For Hooks To Phoenix

Hooks primarily are instantiated in the LiveSocket object in JavaScript. In your LiveView templates, you include hooks to certain elements and every time that element gets rendered or is updated, that hook will run its Javascript code.

Step 1: Define the Hook in JavaScript

To get started, create a hook in a javascript file that is prepared to cover LiveView features.

Usually, the importation of the LiveSocket and the initialisation of the custom hooks are found in the ‘assets/js/app.js’ file in Phoenix.
Here’s how you can define a simple hook:

let Hooks = {};

Hooks.ExampleHook = {
  mounted() {
    console.log("Hook mounted!");
    // Your logic when the hook is attached to an element
  },
  updated() {
    console.log("Hook updated!");
    // Logic when the DOM updates with this element
  },
  destroyed() {
    console.log("Hook destroyed!");
    // Cleanup logic when the element is removed
  }
};

let liveSocket = new LiveSocket("/live", Socket, {
  hooks: Hooks
});

liveSocket.connect();
Enter fullscreen mode Exit fullscreen mode

This example defines a hook named ExampleHook that can respond to lifecycle events such as mounted(), updated(), and destroyed().

  • mounted(): Executes when the element is first rendered.
  • updated(): Executes when the element updates (such as when LiveView re-renders).
  • destroyed(): Executes when the element is removed from the DOM.

Step 2: Use the Hook in Your LiveView Template

After defining your hook in JavaScript, you need to attach it to an element in your LiveView template. You can do this using the phx-hook attribute.

<div id="example" phx-hook="ExampleHook">
  <!-- Your dynamic content goes here -->
</div>
Enter fullscreen mode Exit fullscreen mode

The phx-hook attribute connects the HTML element to the ExampleHook you defined in JavaScript. When this element is rendered or updated by LiveView, the appropriate JavaScript lifecycle methods (e.g., mounted, updated, etc.) will be triggered.

Step 3: Add Custom Behavior

Let’s add some custom behaviour to the hook to demonstrate its capabilities. For example, let's say you want to focus an input field as soon as it is mounted:

Hooks.FocusInput = {
  mounted() {
    this.el.focus();
  },
  updated() {
    this.el.focus();
  }
};
Enter fullscreen mode Exit fullscreen mode

This FocusInput hook will focus the input field whenever it is mounted or updated.

Now, attach this hook to your LiveView template:

<input type="text" phx-hook="FocusInput" placeholder="Focus me!">
Enter fullscreen mode Exit fullscreen mode

When this input field is rendered, it will automatically receive focus, creating a smooth user experience.

Implementing a Chart.js Hook

For a more advanced example, use hooks to integrate a charting library such as Chart.js into a LiveView page.

Step 1: Define the Hook in app.js.

Hooks.Chart = {
  mounted() {
    let ctx = this.el.getContext('2d');
    this.chart = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
          label: '# of Votes',
          data: [12, 19, 3, 5, 2, 3],
          backgroundColor: 'rgba(255, 99, 132, 0.2)',
          borderColor: 'rgba(255, 99, 132, 1)',
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  },
  updated() {
    this.chart.update();
  },
  destroyed() {
    this.chart.destroy();
  }
};
Enter fullscreen mode Exit fullscreen mode

Step 2: Attach the Hook in Your Template

<canvas id="myChart" phx-hook="Chart" width="400" height="400"></canvas>
Enter fullscreen mode Exit fullscreen mode

Now, whenever this canvas element is rendered by LiveView, the chart will be drawn using Chart.js.

That's it for the day. In the next part, we will go through some more concepts of the Phoenix framework.

Feel free to reach out if you need help.

LinkedIn: https://www.linkedin.com/in/rushikesh-pandit
GitHub: https://github.com/rushikeshpandit
Portfolio: https://www.rushikeshpandit.in

#myelixirstatus , #elixir , #phoenixframework

Top comments (0)