Presenting a list of Business on home.html.heex

Hello. I’m creating a site with a list of Business created using the mix phx.gen.live Catalog Business business. I can create the Business using all CRUD screens provided by the LiveView and these pages are under the :require_authenticated_user on router.ex so that only admin (or logged users) can access it.

For my exercise, I’m trying to presenting the list of Business on the standard Home screen provided by Phoenix, so that any user might see this list.

I’m playing around with home.html.heex trying to make it happen. I’m learning how to use Function Components and Live Components for this specific purpose but I cloud’t connect the dots yet. I’m not sure what’s the correct (or feaseable) way to perform this kind of activity.

My plan (once I understand you to present the data) is to transform the standard Phoenix Home page on a aggregator of some data: a block (or component) for a list of Business, list of post, list of comments with higher rating, and so on.

I’m looking forward to read some ideas on how to create it. Thanks :blush:

You don’t need any kind of component to do this.

First of all, for the sake of explanation it’s a little unfortunate you chose the name “business” because I’m going to use the term “business logic” which has nothing to do with your schema called Business :sweat_smile:

So phx.gen.live gives you a “fullstack” set of tools: the business logic as a context (in this case Catalog) plus the web/client stuff as a couple of LiveViews.

The homepage generated by phx.new uses a standard controller + view to show the homepage, so right out of the gate this rules out live components.

If you literally just want to list your businesses (this time I do mean your domain concept!) in the generated homepage, I wouldn’t even worry about function components (it’s not the right tool for the job anyway). Take a look at your Catalog context and figure out how to call that from PageController to in order to display the results on home.html.heex.

All that aside, if you want the DoTheSimplestThingPossible™ solution, find the following line in your router:

  get "/", PageController, :home

and change it to:

  live "/", CatalogLive.Index, :index

This will just show the index page. Probably not exactly what you want but hopefully that gives you a clue!

Mid-air collision with @sodapopcan !

If you want to list the businesses in the home page using the existing plumbing, you will need to do the following:

  1. Update the “home” function /controllers/page_controller.ex to load the businesses from the context, and push the result in the render call for the template as an assign. For example:
  def home(conn, _params) do
    businesses = MyApp.Catalog.list_businesses()
    render(conn, :home, businesses: businesses)
  end
  1. Access the businesses assign in the template to display the business details. So in \controllers\page_html\home.html.heex you would do something like:
  <table>
    <%= for biz <- @businesses do %>
      <tr>
        <td><%= biz.name %></td>
        <td><%= biz.owner %></td>
      </tr>
   <% end %>
  </table>
1 Like

If you want to make function components just to see how they work, you could do something like:

  1. Create a component module (look for core_components.ex and maybe place it in the same folder
defmodule MyBizComponents do
  use Phoenix.Component

  attr :id, :string, required: true
  attr :businesses, :list, default[]

  def biz_table(assigns) do
    ~H"""
      <table>
       <%= for biz <- @businesses do %>
         <.biz_row id={"biz-row-#{biz.id}"} biz={biz} />
       <% end %>
     </table<
   """
  end  

  attr :id, :string, required: true
  attr :biz, :any, required: true
  
  def biz_row(assigns) do
    ~H"""
      <tr>
        <td><%= @biz.name %></td>
        <td><%= @biz.owner %></td>
     </tr<
   """
  end  
end
  1. Update \controllers\page_html\home.html.heex to use them
  < MyBizComponents.biz_table id="biz-table" businesses={@businesses} />

Edit: As @sodapopcan says - probably overkill to use components for a simple table unless you want to use it elsewhere, but hopefully this is a useful example.

1 Like

Bad idea to use this name :smile:

Yes :grinning:
Got it.

Thanks a lot for your answer. I’m gonna sit down and study it.

@mindok it worked perfectly. I could’t find this solution by myself.

Also, I’m gonna try the solution using Function Component just as an exercise.

Thanks a lot.

1 Like