diff --git a/adopt-liveview-notes.md b/adopt-liveview-notes.md
index f8459253..3145dd46 100644
--- a/adopt-liveview-notes.md
+++ b/adopt-liveview-notes.md
@@ -1,38 +1,41 @@
-# Learn Phoenix LiveView
+# Phoenix LiveView Notes
-These notes are from the extremely useful
+These notes are an expansion on the extremely useful
[Adopt Liveview](https://adopt-liveview.lubien.dev/)
course by Lubien Dev.
-If you want deeper explanations and details then definitely check it out!
-The aim of this file is to provide a fast understanding
-of some **core components** of LiveView.
+Our is to capture our own understanding
+of some **core components** of `LiveView`.
-# 1. Fundamentals
+## 1. Fundamentals
-## The PageLive module
+### The PageLive module
-To begin, all the code for our LiveView must be contained inside a module:
+To begin, all the code for our `LiveView` must be contained inside a module:
```elixir
defmodule PageLive do
use OurProjectWeb, :live_view
do
```
-We can name `PageLive` anything, but we normally add "Live" to the end of the
+
+We can name `PageLive` anything,
+but we normally add "Live" to the end of the
module name to indicate that this module is a LiveView.
-Next, we see the line `use OurProjectWeb, :live_view`.
-+ The [`use`](https://hexdocs.pm/elixir/macros.html) macro is in all LiveViews
+Next, we see the line `use OurProjectWeb, :live_view`.
++ The [`use`](https://hexdocs.pm/elixir/macros.html)
+ macro is in all LiveViews
+ `use` executes code at compile time
-+ `live_view` indicates that this module is a LiveView
++ `:live_view` indicates that this module is a `LiveView`
(will see more of how this works in routers)
-## Putting the 'View' in LiveView
-The most basic of LiveViews will contain at minimum a `render/1` function,
-which renders HTML like code called `HEEx` (more on that later).
-It looks a little something like this:
+### Putting the 'View' in LiveView
+
+The most basic `LiveView` contains a `render/1` function,
+which renders `HTML` like code called `HEEx` (more on that later).
+It looks a little something like this:
-```elixir
+```elixir
def render(assigns) do
~H"""
Hello World!
@@ -40,42 +43,46 @@ def render(assigns) do
end
```
-Super basic! Here we're passing in an assigns (which we're about to examine),
-and we contain our `HEEx` code inside the
+Super basic! Here we're passing in an assigns
+(which we're about to examine),
+and we contain our `HEEx` code inside the `~H`
[`sigil_H/2`](https://hexdocs.pm/phoenix_live_view/0.17.0/Phoenix.LiveView.Helpers.html#sigil_H/2S).
> In Elixir, [sigils](https://hexdocs.pm/elixir/sigils.html)
-> are binary functions that essentially transform text into something else
+> are binary functions that essentially transform text into something else
So why are we passing something called `assign` into our function?
-Well, most the time we will want to manage state in our LiveView.
+Most of the time we manage state in our `LiveView`.
This requires us to **store** state somewhere,
-which leads us to `assigns`.
-> _Note: the render function must only and always be
-> passed the argument `assigns`_
+which is done via the `assigns` map.
+
+> **Note**: the render function must always be passed `assigns`.
-## LiveView assigns
+## `LiveView` Assigns
-### Storing state
-In frontend frameworks we need a way to store state
-(e.g in `hooks` in ReactJS).
-In LiveView, we use
+### Storing State
+
+In frontend frameworks we need a way to store state
+(e.g in `hooks` in `React`).
+In `LiveView`, we use
[`assigns`](https://hexdocs.pm/phoenix_live_view/assigns-eex.html):
-+ All LiveView data is stored in the
++ All `LiveView` data is stored in the
[`socket`](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Socket.html)
data struct
+ Your own data is stored under the `assigns` key of said socket
+ (i.e, `assigns` is an [elixir map](https://hexdocs.pm/elixir/1.12/Map.html))
+ In assigns, you can store any variable (lists, maps, structs, etc..)
-To make use of `assigns`, we normally need to use
-the `mount/3` callback function.
+To make use of `assigns`, we use
+the `mount/3` callback function.
+
+### The `mount/3` callback
-### The `mount/3` callback
-LiveView sends information via **callbacks** ( _functions that run when an **event** happens_).
+`LiveView` sends information via **callbacks**
+(_functions that run when an **event** occurs_).
-The `mount/3` callback runs when the LiveView is initialized.
+The `mount/3` callback runs when the `LiveView` is initialized.
It takes three arguments:
@@ -85,26 +92,27 @@ def mount(_params, _session, socket) do
{:ok, socket}
end
```
-We'll talk about the socket next,
-but for now let's break down the parameters being passed in:
-+ `params` are parameters coming from the URL
+The arguments being passed in are:
+
++ `params` are parameters coming from the URL
(e.g. `/users/:id` where `:id` would be one of the params)
+ `session` is data from the current browsing session,
useful for authentication
+ `socket` is our socket data struct that we just spoke about,
it contains data from the current session and holds the `assigns` map
-> Note: as we didn't use `params` or `session` in our code above we let
-> phoenix know this with the underscore: `_params`
+> **Note**: as `params` or `session` are both unused in the code above we let
+> `Phoenix` know this with the underscore; `_params` & `_session`.
Notice that the `mount/3` returns the tuple `{:ok, socket}` if successful.
-+ The `:ok` lets the system know that the mount was successful
+
++ The `:ok` lets the system know that the mount was successful
+ The `socket` gives us access to the new data
### The `%Socket{}` data struct
-State management revolves around modifying state of the `socket`.
+State management revolves around modifying state of the `socket`.
Let's use the [`.dbg/2`](https://hexdocs.pm/elixir/debugging.html#dbg-2)
macro to examine what happens to our assigns map when we modify the socket:
@@ -116,28 +124,29 @@ def mount(_params, _session, socket) do
{:ok, socket}
end
```
+
> Notice that we have to declare a new socket to store the new data?
-> This is because data in Elixir is immutable.
+> This is because data in Elixir is immutable.
The first debug message returns the unaltered `assigns`:
-```
-socket.assigns #=> %{__changed__: %{}, flash: %{}, live_action: :index}
+```elixir
+socket.assigns => %{__changed__: %{}, flash: %{}, live_action: :index}
```
-And the next returns the modified socket with the new `assigns`:
+And the next returns the modified socket with the new `assigns`:
-```
-socket.assigns #=> %{name: "R2-D2", __changed__: %{name: true}, f
-lash: %{}, live_action: :index}
+```elixir
+socket.assigns => %{name: "R2-D2", __changed__: %{name: true},
+ flash: %{}, live_action: :index}
```
-As we can see, assigns are just a map with some data about your LiveView.
-Let's look at its components:
+`assigns` is just a map with some data about the `LiveView`.
+In this case it contains:
+ `name` is the map we added
-+ `__changed__` is a map to explain updates to HTML rendering engine
-+ `flash` is a map to send info, success and alert messages to the user
++ `__changed__` is a map to explain updates to `HTML` rendering engine
++ `flash` is a map to send info, success and alert messages to the client
+ `live_action` use this data to know where we are in the application
(we will see more of this when covering routers)
@@ -145,7 +154,8 @@ Ok, so we've seen how data is stored and what its stored in.
Let's look at how we were render that data.
### Rendering `assigns`
-We render assigns in LiveView using tags: `<%= %>`.
+
+We render assigns in `LiveView` using tags: `<%= %>`.
```elixir
def render(assigns) do
@@ -156,15 +166,15 @@ end
```
Here we're accessing the `name` key from the assigns map using `@name`.
-This is exactly the same as `assigns.name`.
+This is exactly the same as `assigns.name`.
-If we stored an name in assigns when we used the `mount/3` function to
+If we stored an name in assigns when we used the `mount/3` function to
declare a socket, then the code above would render the name, e.g.
"Hello R2-D2".
+### Recap
-### Recap
-We now understand the following:
+We now understand the following:
```elixir
@@ -193,13 +203,16 @@ end
## Modifying state with events
### How do they work?
-For each event in your HEEx, you need a corresponding event handler function:
+
+For each event in your HEEx,
+there is a corresponding event handler function:
```elixir
def handle_event("your_event", _params, socket)
```
It takes:
+
+ The name of the event you wish to handle
+ The event parameters
+ The state of the Socket of the current user
@@ -207,15 +220,15 @@ It takes:
It expects the return of `{:noreply, socket}`, which is basically saying
"Everything is ok! Here is the initial socket"
-> _(Similar to `mount/3`'s `{:ok, socket}`, but `mount/3` followers
+> _(Similar to `mount/3`'s `{:ok, socket}`, but `mount/3` followers
> the Elixir pattern)_
Let's see it in action.
### The `phx-click` event
-Following the pattern of events in the HEEx code, and handling the
-event in a corresponding function we have:
+Following the pattern of events in the HEEx code, and handling the
+event in a corresponding function we have:
```elixir
defmodule PageLive do
@@ -243,55 +256,56 @@ defmodule PageLive do
end
```
-So whats going on here?
+So whats going on here?
-In Phoenix, `phx-click` generates an event of your choosing when the element
-is clicked (shocking, I know).
+In `Phoenix`, `phx-click` generates an event of your choosing when the element
+is clicked.
Let's break down a use case of the code above:
-1. The LiveView is initialized, calling `mount/3` and passing the assigns
+1. The `LiveView` is initialized, calling `mount/3` and passing `assigns`
with our data `name` to the socket
2. The web page displays "Hello R2-D2"
-3. The user clicks on the button, triggering our `phx-click` which generates
+3. The person clicks on the button, triggering our `phx-click`
+ which generates
event with the name `reverse`
-4. Our `handle_event/3` callback is activated, which reverses the string
+4. Our `handle_event/3` callback is activated, which reverses the string
stored in our assign and stores it in a new socket struct
5. The `handle_event/3` returns the new socket
6. The webpage displays "Hello 2D-2R"
-With barely any code, we've triggered and handle an event, and re-rendered the
-page. Elegant right?
+With barely any code, we've triggered and handle an event,
+and re-rendered the page. Elegant right?
### Recap
+
+ Adding `phx-click="event_name"`triggers event when clicked
+ For each event on HEEx, you need a corresponding `handle_event/3` callback
-+ The `mount/3` callback returns `{:ok, socket}`
++ The `mount/3` callback returns `{:ok, socket}`
+ The `handle_event/3` returns `{:noreply, socket}`
-
-
-
+## 2. `HEEx`
-# 2. HEEx
+### `HEEx` is _Not_ `HTML`
-## HEEx is not HTML
-The `sigil_H` in the `render` function returns a data struct called HEEx.
-It is the Phoenix template language, HTML + EEX, where EEx is Embedded Elixir,
-an Elixir template engine.
+The `sigil_H` in the `render` function returns a data struct called `HEEx`.
+It is the `Phoenix` template language, `HTML + EEX`,
+where `EEx` is _Embedded_ `Elixir`,
+an `Elixir` template engine.
> Optimized to know when something has been modified based on its assigns
> and sends the minimum amount of data form server to client
`assigns` is just one of its superpowers.
-## HEEx basics
-Some basic rules of HEEx are as follows:
+## `HEEx` Basics
+
+Some basic rules of HEEx are as follows:
-+ Using the `<%= %>` tag renders Elixir code that is
++ Using the `<%= %>` tag renders Elixir code that is
[Phoenix.HTML.safe](https://hexdocs.pm/phoenix_html/Phoenix.HTML.Safe.html)
-+ Using the `<% %>` tag executes elixir code but does not render anything
-+ `nil` values do not render
++ Using the `<% %>` tag executes elixir code but does not render anything
++ `nil` values do not render
Seeing this in action:
@@ -310,17 +324,17 @@ Case by case renders:
1. The string "R2-D2"
2. The integer 2
-3. The third case just uses the string concatenation operator
-<> whose result is "C-3PO, Human cyborg relations".
+3. The third case just uses the string concatenation operator `<>`
+whose result is "C-3PO, Human cyborg relations".
4. Nothing! Because of the tags do not include the `=` sign,
-the code is executed and because of `IO.puts` you can see the result
-in the terminal
+the code is executed and because of `IO.puts` you can see the result
+in the terminal.
-## Conditional Rendering
+## Conditional Rendering
### Using `if-else` for simple cases
-```elixir
+```elixir
~H"""
<%= if @need_id? do %>
@@ -333,14 +347,15 @@ in the terminal
```
Notice:
+
+ Need the `=` for the `if` tag
+ The `else` and `end` tags don't need `=`
-+ We're getting the assign with `@`
-+ In Elixir we display booleans with `boolean?`
++ We're getting the `assign` with `@`
++ In `Elixir` we display booleans with `boolean?`
-If no `else` block is needed, can simply omit it.
+If no `else` block is needed, can simply omit it.
-But there is a better way..
+But there is a better way ...
### The special `:if` attribute
@@ -353,11 +368,14 @@ directly inside a HTML tag:
"""
```
+Ref:
+https://adopt-liveview.lubien.dev/guides/conditional-rendering/en#the-special-attribute-if
+
### Using `case` for complex cases
-Elixir doesn't have `else-if`, so instead we use `case`.
+Elixir doesn't have `else-if`, so instead we use `case`.
-Let's look at a full LiveView module to see this in action:
+Observe a full `LiveView` module to see this in action:
```elixir
defmodule PageLive do
@@ -402,13 +420,13 @@ end
This is showcasing a combination of previous topics as well `case`.
To go over what we've seen before:
-+ Our assign is `tab` and initialized as "home"
++ The `assign` is `tab` and initialized as "home"
and given to the socket with `mount/3`
+ Using `phx-click="show_{tab_name}"`
-+ Our `handle_event/3` can use
++ Our `handle_event/3` can use
[pattern matching](https://hexdocs.pm/elixir/pattern-matching.html)
-and string concatenation to change the assigns all in one function
-+ We can use HTML `disabled` property to disable a button
+and string concatenation to change the assigns all in one function
++ We can use `HTML` `disabled` property to disable a button
if we're on the correct tab
Let's now talk about the `case`:
@@ -418,15 +436,14 @@ Let's now talk about the `case`:
+ Each condition we do `<% "expected value" -> %>`
+ Note: We can add a default clause with `<% _ -> %>`
-
### Condition chaining with `cond`
When rendering something based on a condition that is not about
equality we use `cond` which follows the logic:
+ Each clause returns `true` or `false`
-+ First condition that returns true ends the flow
-and renders the prescribed html
++ First condition that returns true ends the flow
+and renders the prescribed html
+ To add a standard clause add `true ->` at the **end**
For example:
@@ -458,16 +475,16 @@ For example:
```
### Recap
+
+ For `if-else` use `<%= if condition do %>` and `<% else %>`
+ For only `if` use special if-attribute `:if={condition}` in html tag
+ For multiple comparisons of the same variable
use `<%= case value of %>`
-+ For multiple conditions that don't involve comparing equality
-use `<%= cond do %>`
-+ In all cases, have the `=` in the **first** tag
-
++ For multiple conditions that don't involve comparing equality
+use `<%= cond do %>`
++ In all cases, have the `=` in the **first** tag
-## List rendering
+## List rendering
### Using `for` comprehension and `:for` attribute
@@ -505,7 +522,7 @@ These can solved with streams.
Phoenix's efficient way to handle large (or infinite) lists.
-> Note: In the following code our assign looks clunky since
+> Note: In the following code our assign looks clunky since
> we have to include an id to use streams.
>In reality, this is not an issue as if the data is from a database
> an id will be included.
@@ -539,39 +556,35 @@ end
Let's break it down:
-+ We use the
++ We use the
[`stream/4`](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#stream/4)
function to define a stream
+ `stream/4` recieves our socket, the name of the stream as an atom
and the initial value
-+ Our unordered list (or any parent element of the list) must have
++ Our unordered list (or any parent element of the list) must have
a unique id, in this case `food-stream`
+ Must add `phx-update="stream"` to parent element (to define that
children are part of a stream)
-+ Use special assign `@streams.food`, every time a stream is created
++ Use special assign `@streams.food`, every time a stream is created
with `:some_name` you generate a special assign `@streams.some_name`
+ `:for` now loops with two elements inside a tuple. The id
is useful when wanting to update / delete elements
-### Recap
+### Conclusion
-+ Combining `for` comprehension and special `:for` attribute
++ Combining `for` comprehension and special `:for` attribute
provides simple, readable rendering
+ LiveView provides efficient rendering for large or infinite
data using streams
-
-
-
-
-# 3. Events
+## 3. Events
-## Using phx-value
+### Using `phx-value`
-In the accuracy example, what if we want to include a button
+In the accuracy example, what if we want to include a `