Time to dive into the generated code for the frontend. There is quite a lot to take in from this chapter, so I will try to list my main takeaways:
handle_params(params, url, socket): This is the function that runs after
mount. It is used to handle URL named parameters and live actions.
live actions: Used when one want to have a single live view handle multiple page states. In this case, listing, editing and creating product.
CoreComponents: A module with some fancy premade components ready to be used and/or modified. Learn the available core components for your own benefit!
Attributes: Acts as named variables for your components, they are put inside the tag. Can be defined above the component definition using the
Slots: Can be named or default to
@inner_block. They are markup you put between the opening and closing tag of your component. Can be defined using the
patch link: Changes the URL path and re-routes, but without changing the live view process. Perfect and effective when one want to move to a new live action within the same live view. Since no GET request is actually fired,
mount will not be called, but we will get to
Forms: When you see a form, think of changing data, which mean, think about Changesets. We use the validations defined in the Changeset to validate the form input! Smart!
I didn’t touch on functional components and live components since my list is already quite long, and they will get their own chapters.
I was actually quite surprised when I opened up the index.html.heex, and could not see a single normal HTML tag (actually, I later found one hiding in the table component). Now, all these concepts with components, attributes, slots etc. are great and super powerful, but at the same time I could see it feeling a bit daunting if you have done some HTML/CS/JS and some standard Elixir before, then you open up this file, and suddenly you can’t recognize a single thing.
This is not a criticism at all, just a thought about the experience of learning a new framework/DSL.
Unfortunately, the last part of the chapter regarding creating a new product using the form is a bit outdated. Not only syntax wise, but the logic has changed too.
In the book, they describe that the following happens when a product is saved: If the new product is successfully saved to the DB, we will navigate back to the product index page. This will trigger the
mount function that will make a call to the DB, fetching all product in order to display the new one in the list.
The new generated code is much more efficient!
When the product is successfully sent to the DB, we will send the new product in a message to the parent using the
notify_parent helper function. In the parent, this event is handled using a
handle_info function (see index.ex). Since the list of products is implemented using a stream (also different from the book), the function simply inserts the new product into the stream. After this, we do a patch navigation to the product index page.
This results in 3 major gains (from what I can see):
- Since we use a stream, no data from the list of products is stored on the server, leading to gains in memory efficiency. This might not mean much in this small case, but think about the case when a list might contain thousands of items, and you have thousands of users using the site at the same time. Suddenly there is a lot of memory to be saved.
- Since we use patch instead of navigate, we don’t have to do a slow, pesky GET request.
- Since we send the product from the child component to the parent directly, we don’t have to read a single entry from the database! (Once again, imagine if there were tens of thousands of products in the DB).
I’m sure the outdated code will be fixed for the final revision of the book. ^^
Overall, a great chapter which also makes multiple references to the CRC pattern. But you will probably have to go through it a couple of times in order to pick up on all the new information presented. Sorry for the long post .