Nefcairon

Nefcairon

Project structure // UI components

Hello,

After coding with ruby on rails 2005-2010 I tried to have fun with web development again by trying to use elixir/phoenix 2016 and again 2018. Both times I lost interest after some time. Not that I switched technology-wise, I completely ditched web development at all, thinking that its still not as advanced as I want it to be.

Recently I realized why (at least the main reason).

First, I really think that phoenix is great. Creating a small web application is done pretty quickly. But maintaining and extending the project is a hard task for me - it gets cumbersome as the project grows.

I want to give you an example: When I need to display the contents of a database table on a web page in a so called data table I create the necessary files and functions and declare all the html+css stuff (and maybe include an additional js framework for some fancy behaviour). That’s simple.

But: In one of the next features I certainly want to display another table that should have exactly the same look & feel. So I am reusing what I created before and do a lot of copy & paste. After a few features I end up having a lot of files that all contain almost the same lines of code, just with small differences. This is the opposite of DRY. And whenever I leave my project for a few days, I have a hard time to recall what happens where and each time I want to change the look & feel I have to change it in several files (of course I always miss some).

While I structure and refactor my elixir code by using functions, my frontend stuff just bloats.

What I need to re-enjoy web development is to be able to create a UI component once and easily be able to reuse it as often as I wish. I just want to drop in a data table and tell it the data source it should display and have some options that determine its behaviour (sortable columns, multi or single selection, paging or infinite scrolling, filters etc.).

Is it just me that this is extremely fatiguing? Or are there already solutions/techniques that I just missed?

[Through the last months I came across many concepts that maybe are what I am looking for, but I just cannot put them in relation and neither appear to be simple to use / have a shallow learning curve:
Web Components
Polymer
VUE/React
Material Components
Phoenix.(Live)Component
Surface
Maybe someone wants to shed some light on these]

Most Liked

dimitarvp

dimitarvp

Au contraire, it absolutely is not just you. That is in fact the very reason I willingly gave up my “full stack dev” title some 6 or so years ago. It is soul-crushing to reinvent the same things all the time, over and ever again, always with the ever-to-elusive “only 1% different from the previous file or project” mysterious beast that we can’t seem to ever be able to catch, cage and tame forever.

I’ll not comment on concrete solutions because I don’t have them – I am out of the loop for years. I grumble when I have to do anything more than create / edit 20+ lines of .html.eex files. I just hate it. I can do it just fine but I hate it. It got so bad that as recently as ~7 weeks ago when I had a simple task of adding a few controller actions with views and templates I completely froze and it took me 5 days. Not one of my proudest moments for sure.

The mere fact that we can’t manipulate the glue code of our project – meaning 99% of the Phoenix code in our projects – using commands on the terminal is to me insulting. I know we have generators but they only work one way; sure you’ll generate your stuff but do you have a command like mix phx.controller.parameter.add or mix phx.controller.parameter.change_type (which will create/update a boilerplate validation) or such? Of course not.

This is not bashing Phoenix at all. Phoenix seems to be, in my anecdotal and limited experience, one of the best web frameworks out there. This is more a rant against the entire industry…

IMO most of the web glue code – again, Phoenix controllers, views, templates, helpers, but also Ecto schema modules and even migrations – should be editable with special-tailored terminal commands. Our code editors should not be involved. That’s what I’d call productive.

But… yeah. At least in the meantime many young people can get a taste of what it is to belong to the upper middle class by making money through repeating the same incancantions 500 times until they burn out. :003:

(Also, let’s be friends! :heart: You seem to have almost the same gripes as myself and you seem to approach the problem similarly as well.)

stefanchrobot

stefanchrobot

I’m a very happy user of Surface. My app is a classic server-side rendered Phoenix app (I only use “dead views” - no LiveView stuff). Here’s the markup for a message template index page:

<App conn={@conn} active_link="Templates">
  <PageTitle text="Message templates">
    <PageTitleLink
      type="primary"
      to={Routes.template_path(@conn, :new)}
      icon="plus"
      label="New"
    />
  </PageTitle>

  <div class="flex flex-wrap p-8 gap-8">
    {#for template <- @templates}
      <div class="flex-shrink-0">
        <TemplateCard conn={@conn} template={template} />
      </div>
    {/for}
  </div>
</App>

Here’s a breakdown of the components:

  • App: the application shell with the sidebar nav; highlights the active link,
  • PageTitle: top bar with the title of the page, optional links and tabbed nav,
  • PageTitleLink: CTA button or a back button,
  • TemplateCard: a clickable card with a preview button.

Bringing component system from SPA frameworks is a game changer for me.

I love Tailwind, but my main gripe with it is that it makes the HTML very hard to read (e.g. plain unstyled form vs fully styled form). Components allow me to encapsulate all the markup that only changes the look.

eahanson

eahanson

In addition to the libraries like Surface, Temple, and LiveComponents, you can create your own components using the plain old render/3 function.

From inside your main template, you can render another template:

web/controllers/fruit_controller.ex:

defmodule Web.FruitController do
  use Web, :controller

  def index(conn, _params) do
    render(conn, fruit: GroceryStore.all_fruit())
  end
end

web/templates/fruit/index.html.slim (slime):

h1 Fruit

= render Web.TableView, "table.html", id: "all-fruit", columns: [{"Name", :name}, [{"Rating", :rating}], data: @fruit

web/views/table_view.ex:

defmodule Web.TableView do
  use Web, :view
end

web/templates/table/table.html.slim:

table id=@id
  thead
    tr
      = for {title, _key} <- @columns do
        th= title

  tbody
    = for datum <- @data do
      tr do
        = for {_title, key} <- @columns do
          td= datum[key]

assets/css/app.sass:

@import "components"

table#all-fruit
  @include data-table($padding: 1rem)

assets/css/components.sass:

@mixin data-table($padding: 0.5rem)
  td, th
    font-size: 14px
    padding: $padding

  th
    background-color: blue

So now you’ve got a reusable, parameterized table component to render HTML, and a reusable, parameterized Sass function to render CSS. That should give you a nice combination of reuse and customizability.

Last Post!

wallyfoo

wallyfoo

I would rather pet a live scorpion than style one more login form. I crossed my burnout threshold years ago.

Phoenix makes web development tolerable for me, but I foist off as much front-end stuff as I can these days. Why can’t I just build systems in peace?

Where Next?

Popular in Discussions Top

ricklove
I was just introduced to Elixir and Phoenix. I was told about the 2 million websocket test that was done 2 years ago. From my research, t...
New
jer
I’ve been using umbrellas for a while, and generally started off (on greenfield projects at least) by isolating subapps based on clearly ...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
tomekowal
Hey guys! I want to create a toy project that shows a chart of temperature over time and updates every 5 seconds. I feel LiveView is per...
New
mmmrrr
Just saw that dhh announced https://hotwire.dev/ Is it just me or is this essentially live view? :smiley: Although I like the “iFrame-e...
New
AstonJ
Can you believe the first professionally published Elixir book was published just 8 years ago? Since then I think we’ve seen more books f...
New

Other popular topics Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement