DEV Community

Diogo Oliveira
Diogo Oliveira

Posted on

Creating a simple todo app with hotwire + sqlite3

tldr

Simple todo app that shows how to use stimulus and turbo for the tasks creation.

To begin with, I create a model task, with name and completed as columns and then I created the index, create and destroy actions for the tasks_controllers.

With you want to see the code, access this link: https://github.com/diogobest/todo-hotwire-example/blob/main/app/controllers/tasks_controller.rb

Our model is like this:

class Task < ApplicationRecord
  broadcasts_to -> (task) { :tasks } #1
end
Enter fullscreen mode Exit fullscreen mode
  1. broadcasts_to creates an pub/sub channel called tasks. Every change like create, update, destroy from this model, will be sent to this channel. Later we will connect to it.

The code is very simple, I don’t want to lose focus or add unnecessary complexity, feel free to clone / fork the project and change as you want.

The next step is to create our views in project/views/tasks/index.html.erb. This file is the core of the this sample app. Here we’ll have the features to complete our task, to delete or add them. The code is very simple:

<%= turbo_frame_tag :tasks do %>  ## 1
  <%= render "form" %> ## 2
<% end %>

<%= turbo_stream_from :tasks %> ## 3
<%= render @tasks %> ## 4

Enter fullscreen mode Exit fullscreen mode

See the code at: https://github.com/diogobest/todo-hotwire-example/tree/main/app/views

  1. The turbo_frame_tag creates an empty frame content, but fetches the tasks stream of contents that we created in our models
  2. This create the form to add a new task, the code is simple:
<%= form_with scope: :task, data: { turbo_frame: "_top" } do |form| %>
  <%= form.label :name %>
  <%= form.text_field :name, required: true %>
  <%= form.label :completed %>
  <%= form.check_box :completed %>
  <%= form.submit "Save" %>
<% end %>
Enter fullscreen mode Exit fullscreen mode
  1. Connect to the tasks channel, it is the channel we created at the Task model.
  2. Render each task individually.
<%= turbo_frame_tag dom_id(task) do %>
  <div data-controller="tasks" data-tasks-id-value="<%= task.id %>" data-tasks-completed-value="<%= task.completed %>">
    <input
      type="checkbox"
      <%= "checked" if task.completed %>
      data-action="click->tasks#toggle"
    />
    <h3> <%= task.name %></h3>
    <%= link_to 'Deletar', task_path(task.id), data: { turbo_method: :delete } %>
</div>
<% end %>
Enter fullscreen mode Exit fullscreen mode

The only consideration I have to do is the dom_id(task) command, that is getting the id of the task and creating a string like: “task_01”.

Execute the app and try to delete and create new tasks

Top comments (0)