Lesson 3 — Layouts in Phlex
In Rails with ERB, layouts are a special concept — separate files with mysterious yield behaviour and content_for for hoisting content up from views into the layout. In Phlex, layouts are just components. There is nothing special to learn.
We will cover three approaches to wiring up a layout. But first, let’s build the layout component itself — it is the same regardless of which approach you choose.
Step 1 — Build AppLayout
Create the directory and file:
|
|
|
|
This is a standard Phlex component. It accepts a title: prop, renders the full HTML document structure, and yields to render the page content inside <main>. Nothing layout-specific about it — it just happens to contain doctype and <html>.
Step 2 — Choose how to wire it up
There are three approaches. Read all three, then see which one KanbanFlow uses and why.
Approach 1 — Composition
Each view renders the layout explicitly, passing its content as a block:
|
|
Every view is completely explicit about which layout it uses and what title it passes. This is the simplest approach to understand — there is no around_template hook or base class magic to reason about. Each view is self-contained.
The downside is repetition — every view has render Views::Layouts::AppLayout.new(title: "...") do ... end wrapping its content.
Approach 2 — Inheritance via around_template
The base view class handles the layout wrapping automatically. Individual views just define their content and optionally override page_title:
|
|
|
|
Views are now minimal — just a title override and content. The layout wrapping is invisible. around_template is a Phlex hook that wraps the call to view_template — super is where the view’s own content renders.
Approach 3 — Legacy ERB compatibility
If you are in a hybrid setup and want a Phlex layout that still wraps non-Phlex ERB views, include Phlex::Rails::Layout:
|
|
|
|
This lets ERB views render inside a Phlex layout without any changes to the views themselves. The right choice during migration when some views are still ERB and others are Phlex.
Step 3 — What KanbanFlow uses
KanbanFlow uses Approach 2 — inheritance via around_template.
Composition (Approach 1) is the simplest to understand and perfectly valid. We choose inheritance because KanbanFlow has many views and the repetition of wrapping every view explicitly would add noise without benefit. With around_template in Views::Base, every view gets the layout for free — there is nothing to remember and nothing to repeat.
Update Views::Base to add around_template while keeping the generated cache_store:
|
|
Views::Base inherits from Components::Base — so it already has Literal Properties, class_names, Routes helpers, and the Kit available. No need to add anything else.
Exercise
Create Views::Layouts::AppLayout as shown. Update Views::Base with around_template. Create a minimal placeholder view:
|
|
Add a route and controller action:
|
|
|
|
Run the app using bin/dev, then visit http://localhost:3000. You should see the nav, the heading inside <main>, and “Welcome” in the browser tab.