Skip to content

kimlindholm/phoenix_component_folders

Repository files navigation

Phoenix Component Folders

CircleCI Ebert codebeat badge

Reusable UI components on Phoenix framework

Quick tutorial and demo app

Description

If you're using Phoenix to render rich UI components (à la React or Vue), it might be more convenient to group all related code and tests into separate component folders and to make use of some view helpers:

Phoenix Component Folders Screenshot

Here's how to do it on Phoenix 1.3. If you're using version 1.2, just note some minor changes like replacing path lib/my_app_web with web.

Tutorial

Step 1: Add component_helpers.ex

Grab file component_helpers.ex and place it in new folder lib/my_app_web/components.

Step 2: Edit lib/my_app_web.ex

-  def view do
+  def view(opts \\
+      [root: "lib/my_app_web/templates",
+       namespace: MyAppWeb]) do
     quote do
-      use Phoenix.View, root: "lib/my_app_web/templates",
-                        namespace: MyAppWeb
+      use Phoenix.View, unquote(opts)

       # etc...

       import MyAppWeb.Gettext
+      import MyAppWeb.Components.ComponentHelpers
     end
   end

   # etc...

   defmacro __using__(which) when is_atom(which) do
     apply(__MODULE__, which, [])
   end
+  defmacro __using__({which, opts}) when is_atom(which) do
+    apply(__MODULE__, which, [opts])
+  end
 end

Step 3: Add View

Next, you'll need to add a view for each component namespace. For instance, as in the screen shot above, for namespace :comment_feed you'd create file lib/my_app_web/components/comment_feed/comment_feed_view.ex:

defmodule MyAppWeb.Components.CommentFeedView do
  alias MyAppWeb.Components.ComponentHelpers
  use MyAppWeb, {:view, ComponentHelpers.view_opts(:comment_feed)}
end

Done

That's it. Now you're ready to add some templates. See commits Add example components and Migrate example components to the new 1.3 directory structure for a minimal example and add controllers / channels to your UI components as needed. Let's finish up with some usage examples:

<%= c :comment_feed, :comments, assigns %>   <!-- pass all assigns from controller -->
<%= c :comment_feed, :reply_form %>          <!-- no assigns -->
<%= c :comment_feed %>                       <!-- default to index.html.eex template -->

In all the code above, remember to replace occurences of MyApp, my_app, PhoenixComponentFolders and phoenix_component_folders with your app's name.

Original Articles and Code

Demo App

Requirements

  • Phoenix 1.3.0 or later
  • Elixir 1.7 or later
  • Erlang 21 or later

Installation

To start your Phoenix server:

  • Install dependencies with mix deps.get
  • Install Node.js dependencies with cd assets && npm install
  • Start Phoenix endpoint with mix s

Now you can visit localhost:4000 from your browser.

License

See LICENSE.