You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/components.md
+20-10Lines changed: 20 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,14 +4,20 @@
4
4
5
5
> **Requirement**: This guide expects that you have gone through the [request life-cycle guide](request_lifecycle.html).
6
6
7
-
The Phoenix endpoint pipeline takes a request, routes it to a controller, and calls a view module to render a template. The view interface from the controller is simple – the controller calls a view function with the connections assigns, and the function's job is to return a HEEx template. We call any function that accepts an `assigns` parameter and returns a HEEx template a *function component*. Function components are defined with the help of the [`Phoenix.Component`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html) module.
7
+
The Phoenix endpoint pipeline takes a request, routes it to a controller, and calls a view module to render a template. The view interface from the controller is simple – the controller calls a view function with the connections assigns, and the function's job is to return a HEEx template. We call any function that accepts an `assigns` parameter and returns a HEEx template a *function component*.
8
8
9
-
Function components are the essential building block for any kind of markup-based template rendering you'll perform in Phoenix. They serve as a shared abstraction for the standard MVC controller-based applications, LiveView applications, layouts, and smaller UI definitions you'll use throughout other templates.
9
+
> The Phoenix framework is designed for HTML applications, JSON APIs, GraphQL endpoints, etc. For this reason, all of the functionality related to HTML rendering comes as part of two separate packages:
10
+
>
11
+
> *[`phoenix_html`](https://hexdocs.pm/phoenix_html) - defines the building blocks for writing HTML safely. In your project, you'll interact primarily with the `Phoenix.HTML` module, which is imported by default in all templates
12
+
>
13
+
> *[`phoenix_live_view`](https://hexdocs.pm/phoenix_live_view) - a library for rich, real-time user experiences with server-rendered HTML. While LiveView provides several abstraction for building collaborative and dynamic applications, it also defines the `HEEx` template language, function components, and JS commands, which brings powerful abstractions for all kinds of server-rendered HTML applications
10
14
11
-
In this chapter, we will recap how components were used in previous chapters and find new use cases for them.
15
+
In this chapter, we will recap how components are used and dig deeper to discover new use cases.
12
16
13
17
## Function components
14
18
19
+
Function components are the essential building block for any kind of markup-based template rendering you'll perform in Phoenix. They serve as a shared abstraction for the standard MVC controller-based applications, LiveView applications, layouts, and smaller UI definitions you'll use throughout other templates. Their documentation is available in [the `Phoenix.Component` module](https://hexdocs/phoenix_live_view/Phoenix.Component.html).
20
+
15
21
At the end of the Request life-cycle chapter, we created a template at `lib/hello_web/controllers/hello_html/show.html.heex`, let's open it up:
16
22
17
23
```heex
@@ -31,7 +37,7 @@ At the end of the Request life-cycle chapter, we created a template at `lib/hell
31
37
...
32
38
```
33
39
34
-
A function component is just a function that receives a map of `assigns` as argument and renders part of a template using the `~H` sigil. Let's try defining our own component by hand.
40
+
So far, all of the function components we have defined also worked as templates. Let's learn more about them by defining our own component with the intent of encapsulating some HTML markup.
35
41
36
42
Imagine we want to refactor our `show.html.heex` to move the rendering of `<h2>Hello World, from {@messenger}!</h2>` to its own function. Remember that `show.html.heex` is embedded within the `HelloHTML` module. Let's open it up:
37
43
@@ -61,7 +67,7 @@ defmodule HelloWeb.HelloHTML do
61
67
end
62
68
```
63
69
64
-
We declared the attributes we accept via the `attr/3` macro provided by `Phoenix.Component`, then we defined our `greet/1` function which returns the HEEx template.
70
+
We declared the attributes we accept via the [`Phoenix.Component.attr/3`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#attr/3) macro, then we defined our `greet/1` function which returns the HEEx template.
65
71
66
72
Next we need to update `show.html.heex`:
67
73
@@ -73,17 +79,21 @@ Next we need to update `show.html.heex`:
73
79
</Layouts.app>
74
80
```
75
81
76
-
When we reload `http://localhost:4000/hello/Frank`, we should see the same content as before. Since the `show.html.heex` template is embedded within the `HelloHTML` module, we were able to invoke the function component directly as `<.greet messenger="..." />`. If the component was defined elsewhere, we would need to give its full name: `<HelloWeb.HelloHTML.greet messenger="..." />`.
82
+
When we reload `http://localhost:4000/hello/Frank`, we should see the same content as before! The `show.html.heex` is now invoking two different funcion components:
83
+
84
+
* `<Layouts.app` - the syntax for invoking function componente defined in a separate module and it follows the same rules as calling any other function in Elixir
85
+
86
+
* `<.greet` - when the function component is defined in the same module as the template, we can skip the module name, and invoke the component using its name prefixed with a dot
77
87
78
-
By declaring attributes as required, Phoenix will warn at compile time if we call the `<.greet />` component without passing attributes. If an attribute is optional, you can specify the `:default` option with a value:
88
+
Since the `show.html.heex` template is embedded within the `HelloHTML` module, we were able to invoke the function component directly as `<.greet messenger="..." />`. If the component was defined elsewhere, we would need to give its full name, such as: `<HelloWeb.HelloHTML.greet messenger="..." />`.
89
+
90
+
By declaring attributes as required, Phoenix will warn if we call the `<.greet />` component without passing attributes. If an attribute is optional, you can specify the `:default` option with a value:
79
91
80
92
```
81
93
attr :messenger, :string, default: nil
82
94
```
83
95
84
-
Overall, function components are the essential building block of Phoenix rendering stack. The majority of the times, they are functions that receive a single argument called `assigns` and call the `~H` sigil, as we did in `greet/1`. They can also be invoked from templates, with compile-time validation of its attributes declared via `attr`.
85
-
86
-
Next, let's fully understand the expressive power behind the HEEx template language.
96
+
Overall, function components are the essential building block of Phoenix rendering stack. Next, let's fully understand the expressive power behind the HEEx template language.
Copy file name to clipboardExpand all lines: guides/controllers.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -159,8 +159,6 @@ Or you can pass the assigns directly to `render` instead:
159
159
160
160
Generally speaking, once all assigns are configured, we invoke the view layer. The view layer (`HelloWeb.HelloHTML`) then renders `show.html` alongside the layout and a response is sent back to the browser.
161
161
162
-
[Components and HEEx templates](components.html) have their own guide, so we won't spend much time on them here. What we will look at is how to render different formats from inside a controller action.
163
-
164
162
## New rendering formats
165
163
166
164
Rendering HTML through a template is fine, but what if we need to change the rendering format on the fly? Let's say that sometimes we need HTML, sometimes we need plain text, and sometimes we need JSON. Then what?
Copy file name to clipboardExpand all lines: guides/request_lifecycle.md
+21-33Lines changed: 21 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,9 +117,9 @@ defmodule HelloWeb.HelloHTML do
117
117
end
118
118
```
119
119
120
-
To add templates to this view, we can define them as function components in the module or in separate files.
120
+
To add templates to this view, we can define them as functions in the module or in separate files.
121
121
122
-
Let's start by defining a function component:
122
+
Let's start by defining a function:
123
123
124
124
```elixir
125
125
defmoduleHelloWeb.HelloHTMLdo
@@ -133,11 +133,9 @@ defmodule HelloWeb.HelloHTML do
133
133
end
134
134
```
135
135
136
-
We defined a function that receives `assigns` as arguments and used [the `~H` sigil](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2) to specify the content we want to render. Inside the `~H` sigil, we used a templating language called HEEx, which stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site Scripting with no extra work on your part.
136
+
We defined a function that receives `assigns` as arguments and used [the `~H` sigil](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2) to specify the content we want to render. Inside the `~H` sigil, we used a templating language called HEEx, which stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site Scripting with no extra work on your part. We say that any function that receives `assigns` and returns templates to be a **function component**.
137
137
138
-
A template file works in the same way. Function components are great for smaller templates and separate files are a good choice when you have a lot of markup or your functions start to feel unmanageable.
139
-
140
-
Let's give it a try by defining a template in its own file. First, delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
138
+
A template file works in the same way. Let's give it a try by defining a template in its own file. First, delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
141
139
142
140
```elixir
143
141
defmoduleHelloWeb.HelloHTMLdo
@@ -147,54 +145,44 @@ defmodule HelloWeb.HelloHTML do
147
145
end
148
146
```
149
147
150
-
Here we are telling `Phoenix.Component` to embed all `.heex` templates found in the sibling `hello_html` directory into our module as function definitions.
148
+
Here we are saying we want to embed all `.heex` templates found in the sibling `hello_html` directory into our module as function components.
149
+
150
+
Next, we need to add files to the `lib/hello_web/controllers/hello_html` directory. A template file has the following structure: `NAME.FORMAT.TEMPLATING_LANGUAGE`. In our case, let's create an `index.html.heex` file at `lib/hello_web/controllers/hello_html/index.html.heex`:
151
151
152
-
Next, we need to add files to the `lib/hello_web/controllers/hello_html` directory.
152
+
```heex
153
+
<section>
154
+
<h2>Hello World, from Phoenix!</h2>
155
+
</section>
156
+
```
153
157
154
-
Note the controller name (`HelloController`), the view name (`HelloHTML`), and the template directory (`hello_html`) all follow the same naming convention and are named after each other. They are also collocated together in the directory tree:
158
+
Phoenix will see the template file and compile it into an `index(assigns)` function, similar as before. There is no runtime or performance difference between the two styles.
155
159
156
-
> **Note**: We can rename the `hello_html` directory to whatever we want and put it in a subdirectory of `lib/hello_web/controllers`, as long as we update the `embed_templates` setting accordingly. However, it's best to keep the same naming convention to prevent any confusion.
160
+
Also note the controller name (`HelloController`) and the view name (`HelloHTML`) and their respective files, `hello_controller.ex` and `hello_html.ex` all follow the same naming convention. and are named after each other. You could name the directory anything you want, as long as you update the `embed_templates` setting accordingly, but it's best to follow conventions.
157
161
158
162
```console
159
163
lib/hello_web
160
164
├── controllers
161
165
│ ├── hello_controller.ex
162
166
│ ├── hello_html.ex
163
167
│ ├── hello_html
164
-
| ├── index.html.heex
168
+
| ├── index.html.heex (NEW FILE!)
165
169
```
166
170
167
-
A template file has the following structure: `NAME.FORMAT.TEMPLATING_LANGUAGE`. In our case, let's create an `index.html.heex` file at `lib/hello_web/controllers/hello_html/index.html.heex`:
168
-
169
-
```heex
170
-
<section>
171
-
<h2>Hello World, from Phoenix!</h2>
172
-
</section>
173
-
```
174
-
175
-
Phoenix will see the template file and compile it into an `index(assigns)` function, similar as before. There is no runtime or performance difference between the two styles.
176
-
177
171
Now that we've got the route, controller, view, and template, we should be able to point our browser at [http://localhost:4000/hello](http://localhost:4000/hello) and see our greeting from Phoenix!
In case you stopped the server along the way, the task to restart it is `mix phx.server`. If you didn't stop it, everything should update on the fly: Phoenix has hot code reloading!
182
176
183
-
> A note on hot code reloading: some editors with their automatic linters may prevent hot code reloading from working. If it's not working for you, please see the discussion in [this issue](https://github.com/phoenixframework/phoenix/issues/1165).
184
-
185
177
## Layouts
186
178
187
-
188
-
189
-
Also, even though our `index.html.heex` file consists of only a single `section` tag, the page we get is a full HTML document. Our index template is actually rendered into a separate layout: `lib/hello_web/components/layouts/root.html.heex`, which contains the basic HTML skeleton of the page. If you open this file, you'll see a line that looks like this at the bottom:
179
+
Even though our `index.html.heex` file consists of only a single `section` tag, the page we get is a full HTML document. Our index template is actually rendered into a separate layout: `lib/hello_web/components/layouts/root.html.heex`, which contains the basic HTML skeleton of the page. If you open this file, you'll see a line that looks like this at the bottom:
190
180
191
181
```heex
192
182
{@inner_content}
193
183
```
194
184
195
-
This line injects our template into the layout before the HTML is sent off to the browser. We will talk more about layouts in the Controllers guide.
196
-
197
-
The rest of the page structure is included in the `app` component that is defined in the `lib/hello_web/components/layouts.ex` module.
185
+
This line injects our template into the layout before the HTML is sent off to the browser. The root layout, as the name implies, is a barebone layout with mostly the `<head>` tag and a structure that is shared across **all of your pages**. Richer features, such as sidebar, menus, etc. are part of your application layout, which we will explore in a couple sections below.
198
186
199
187
## From endpoint to views
200
188
@@ -293,14 +281,14 @@ If you point your browser to [http://localhost:4000/hello/Frank](http://localhos
293
281
294
282

295
283
296
-
Let's break what the template does into parts. This template has the `.heex` extension. HTML templates in Phoenix are written in HEEx, which stands for (HTML + Embedded Elixir). There are three features from HEEx we are using in the template above:
284
+
Let's break what the template does into parts. This template has the `.heex` extensionwhich stands for HTML + Embedded Elixir). There are three features from HEEx we are using in the template above:
297
285
298
-
*Function components, as in `<Layouts.app>` - they are the essential building block for any kind of markup-based template rendering you'll perform in Phoenix. This particular component will abstract our app layout, such as menu and sidebar, and then render the contents inside
286
+
*Assigns, such as `@messenger` and `@flash` - values we pass to the view from the controller are collectively called our "assigns". We could access our messenger value via `assigns.messenger` and `assigns.flash`, but Phoenix gives us the much cleaner `@` syntax for use in templates.
299
287
300
288
* Content interpolation, such as `{@messenger}` - any Elixir code that goes between `{...}` will be executed, and the resulting value will replace the tag in the HTML output
301
289
302
-
*Assigns, such as `@messenger` and `@flash` - values we pass to the view from the controller are collectively called our "assigns". We could access our messenger value via `assigns.messenger` and `assigns.flash`, but Phoenix gives us the much cleaner `@` syntax for use in templates.
290
+
*Function component tags, as in `<Layouts.app>` - the reason templates are called function components is because we can compose them! In this case, there is an `HelloWeb.Layouts.app` function, that defines our application layout, which we invoke with our custom content
303
291
304
-
Also note how these three features compose: we are passing the `@flash` assign as an Elixir value to the `<Layouts.app>` component. As we will learn later, flash messages are used to display temporary messages to the user, such as success or error messages.
292
+
Also note how these three features compose: we are passing the `@flash` assign as an Elixir value to the `<Layouts.app>` component. As we will learn later, flash messages are used to display temporary messages to the user, such as success or error messages. We will learn more about them in the [Components and HEEx templates](components.html) guide.
305
293
306
294
We are done! Feel free to play around a bit. Whatever you put after `/hello/` will appear on the page as your messenger.
Copy file name to clipboardExpand all lines: guides/routing.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -184,8 +184,8 @@ Notice how the first call to an existing route, `~p"/comments"` gave no warning,
184
184
Phoenix projects are set up out of the box to allow use of verified routes throughout your web layer, including tests. For example in your templates you can render `~p` links:
0 commit comments