Button Clicks
Notes & Exercises
Final Code
You'll find the completed example in the 1-button-clicks-end
branch
of the code bundle.
Version 0.16 Update
In the video we created a LiveView LEEx
template using the special ~L
sigil. LiveView 0.16 introduced a new HEEx
template which is created using the ~H
sigil.
Don't worry: Both types of templates are fully supported in LiveView 0.16. However, HEEx
templates have several advantages including compile-time validation of the markup in the template. So it's worth using HEEx
templates on your own projects. And the good news is that it's relatively easy to migrate from an LEEx
template to an HEEx
template.
Most of the time, you just need to make two trivial changes:
-
Replace the
~L
sigil with the~H
sigil. So change this~L"""
to this
~H"""
-
Use
{}
to interpolate code inside HTML tags.Since
HEEx
templates must parse and validate the HTML, code interpolation using<%= ... %>
and<% ... %>
are restricted to the body (inner content) of HTML elements and it cannot be used inside HTML tags.For example, the
LEEx
template forLightLive
includes this section:<span style="width: <%= @brightness %>%"> <%= @brightness %>% </span>
That syntax is valid in an
LEEx
template, but invalid in anHEEx
template because it uses<%= ... %>
to interpolate code inside thespan
tag.HEEx
templates require Elixir expressions inside tags to appear within{}
. We can make it a validHEEx
template like so:<span style={"width: #{@brightness}%"}> <%= @brightness %>% </span>
Notice that within the
{}
we now have an Elixir expression that evaluates to a string. It uses standard Elixir string interpolation (#{}
) to interpolate the value of the@brightness
value.Also notice that the
<%= @brightness %>
expression on the second line remains valid (no changes necessary) because it's in the body of thespan
element and not inside thespan
tag itself.
In subsequent notes we'll highlight any special cases when it comes to HEEx
migration. And in the final_app_v0.16
directory of the code bundle you'll find a version of all the course code updated for LiveView 0.16. But we recommend sticking with LEEx
templates as you go through the course so you can focus on the core concepts.
The Generated App
You might be wondering how we created the Phoenix app we started with in the 1-button-clicks-begin
branch. We generated it using:
mix phx.new live_view_studio --live
Then we tossed in some images and added TailwindCSS with some custom CSS to give the examples
a more polished feel. Other than that cosmetic stuff, the code in the
1-button-clicks-begin
branch is a standard Phoenix app.
Creating Your Own App
If you'd like to create your own app that has the same CSS styles and images as the live_view_studio
app, here's how you'd go about it:
-
First, assuming you don't already have an application directory, generate one:
mix phx.new my_app --live
-
Then copy the
assets/package.json
file from thelive_view_studio
application to theassets
directory of your app, and then install the dependencies:cd assets npm install
-
Then to mimic how we have Tailwind configured, copy the following configuration files from the
live_view_studio
application to theassets
directory in your app:assets/tailwind.config.js assets/webpack.config.js assets/postcss.config.js
-
In terms of CSS and image files, copy all of them from the
live_view_studio
application to the respective subdirectories of yourassets
directory:assets/css/*.css assets/static/images/*
-
Finally, at the top of your
assets/js/app.js
file, change this line which expects that you're using Sassimport "../css/app.scss"
to this which expects a regular CSS file:
import "../css/app.css"
And that should give you a baseline application with all the images and styles in place matching what you'll see in the course!
How's Your Elixir Game?
As you saw in the video, you write LiveViews using the Elixir programming language. If you're new to the language, learning LiveView might feel like someone tied your shoe laces together and asked you play some hoops. 🏀 🤕
Imagine knowing Elixir so well you can drive to the basket and dunk! That's what you'll be able to do after our Elixir & OTP course. So before getting too far into LiveView, we highly recommend joining us in the Elixir course to gain clarity and confidence with the language.
We start with the Elixir fundamentals and leave no stone unturned as we build an app step-by-step from scratch. And the second half is all about OTP, so it's like getting two courses in one. 🙌
We think you're gonna love it!
Exercises and Modifying the Code
Throughout the course we'll suggest exercises to apply what you learned in the videos. You might also decide to make your own modifications to our code. By all means, tinker away!
You have a couple choices as to where you make those modifications.
One option is to change the code in the Git branch of the local repository that's included in the code bundle. For example, you could make changes in the 1-button-clicks-end
branch. However, when you switch to the 2-dynamic-form-begin
branch (coming up next), any changes you made in the
1-button-clicks-end
branch won't come along for the ride. To integrate your changes, you would need to merge them into the 2-dynamic-form-begin
branch. And every time you switched to the next branch, you would need to merge your changes from the previous branch.
Another option is create your own separate repository that includes your exercise solutions and modifications, and copy over files from the code bundle repo as necessary. In this scenario there's no need to merge branches as you'll likely just keep everything in the main branch.
Both options have their pros and cons. Which one you choose is a matter of personal preference. But it's good to have a game plan because here comes the first exercise...
Exercise: Light Me Up!
Add a "Light Me Up!" button that when clicked sets the brightness to a random number between 0 and 100. Try doing it from memory before peeking at the answer for guidance. 😉
-
Add a button that emits an event when clicked.
-
Handle the event by assigning a random number as the brightness.
-
Throw a disco party! 🕺
Min and Max Brightness
Now you may have noticed (as @jaimeiniesta did) that you can continue to turn the light up even after it's reached full brightness. Same with turning it down even when it's already off.
Here's his neat solution using min
and max
:
def handle_event("up", _, socket) do
socket = update(socket, :brightness, &min(&1 + 10, 100))
{:noreply, socket}
end
def handle_event("down", _, socket) do
socket = update(socket, :brightness, &max(&1 - 10, 0))
{:noreply, socket}
end