and down ... up and down ...
This is an actual piece of view code that I wrote recently:
<%= render "folder_tasks/task_grid", folder: folder, task_type: task_type, scope: scope, sort_order: sort_order do %> <%= card_panel do %> <% if tasks.empty? %> <%= action_bar style: :between do %> <%= t "tasks.there_are_no_tasks", tasks: task_type.plural %> <%= link_to icon_for("add_task", t("tasks.add_task", task_type: task_type)), new_folder_task_type_task_path(folder), class: "btn btn-outline-primary" if can? :add_task, folder %> <% end %> <% else %> <% tasks.each do |task| %> <%= render "folder_tasks/task", task: task, folder: folder, task_type: task_type %> <% end %> <% end %> <% end %> <% end %>
If you know Rails, you'll see that there's a container partial - "task_grid", that draws out the container for a set of tasks (which in turn calls another partial - "folder_layout" which draws out the tabs relevant to that folder, all of which is rendered within the application layout, which includes a header, footer and sidebar).
Within the grid, we have a "card_panel" that contains an "action_bar" that has a "new task" link. The action bar is only drawn if there are no tasks; if there are tasks, then each one is drawn out using it's own "task" partial.
This is relatively clean for a Rails app - certainly a lot better than some of the projects that I've inherited off other developers.
But I think it should look like this:
<folder-page folder-data="<%= folder.to_json %>"> <task-grid task-type-data="<%= task_type.to_json %>" scope="<%= scope %>" sort-order="<%= sort_order %>"> <card-panel> <list count=<%= tasks.count %>> <section slot="no-items"> <caption><%= t "tasks.there_are_no_tasks", tasks: task_type.plural %>"></caption> <add-button show-if=<%= can? :add_task, folder %> href="<%= new_folder_task_type_task_path(folder) %>"> <icon type="add_task"><%= t("tasks.add_task", task: task_type.to_s)) %></icon> </add-button> </section> <section slot="items"> <% tasks.each do |task| %> <task-list-item task-data="<%= task.to_json"></task-list-item> <% end %> </section> </list> </card-panel> </task-grid> </folder-page>
Each element of the page is then represented by some markup that describes what that element is. Each element knows how to display itself - a "task-list-item" is given the JSON representing that task and knows what to draw. Or even better, it's optionally given a URL, it fetches the JSON from the server and then knows what to draw. If anything, the worst thing about this version are the ERB
For this reason, I'm now looking at web-components. Shoelaces, a library of prebuilt components looks amazing. Svelte is the new hotness for building them, but there's always been a part of me that likes Vue.
I'll let you know how I get on.