Schemaless Changesets in LiveView

Let's learn how to build a LiveView backed by schemaless changesets.

Suppose: To celebrate the one-week anniversary of our wildly successful game company, we’re offering a special promotion.

Any registered user can log in and visit the /promo page. There, they can submit a friend’s email address, and our app will email a promo code to that person providing 10% off of their first game purchase.

We’ll need to provide a form for the promo recipient’s email, but we won’t be storing this email in our database. We don’t have that person’s permission to persist their data, so we’ll use a schemaless changeset to cast and validate the form input. That way, the email layer will only send promotional emails to valid email addresses.

Let’s plan a bit.


We’ll need a new /promo LiveView with a form backed by a schemaless changeset. The form will collect a name and email for a lucky 10% off promo recipient. Changeset functions are purely functional, so we’ll build a model and some changeset functions in a tiny core. You’ll notice that once we’ve coded up the schemaless changeset, the LiveView will work the same way it always has, displaying any errors for invalid changesets and enabling the submit button for valid ones.

We’ll start in the core. The Promo.Recipient core module will—you guessed it—model the data for a promo recipient. It will have a converter to produce the changeset that works with the LiveView’s form. Then, we’ll build a context module, called Promo that will provide an interface for interacting with Promo.Recipient changesets.

The context is the boundary layer between our predictable core and the outside world. It is the home of code that deals with uncertainty. It will be responsible for receiving the uncertain form input from the user and translating it into predictable changesets. The context will also interact with potentially unreliable external services, which in this case is the code that sends the promotional emails. We won’t worry about the email sending code. We’ll keep our focus on changesets in LiveView and create a tiny stub instead.

Once we have the backend wired up, we’ll define a LiveView, PromoLive, that will manage the user interface for our feature. We’ll provide users with a form to input the promo recipient’s name and email. That form will apply and display any recipient validations we define in our changeset, and the LiveView will manage the state of the page in response to invalid inputs or valid form submissions.

Let’s get started!

Get hands-on with 1200+ tech skills courses.