O que um controller Stimulus conecta
O espaço entre HTML puro e um framework JS completo
Um dropdown que abre e fecha, um campo de senha com medidor de força, um diálogo que fecha quando você clica fora dele: nada disso precisa de um framework que renderize views no navegador. Cada um precisa de HTML comum, renderizado no servidor, com um pouco de comportamento preso a elementos específicos. O Stimulus foi feito para esse espaço, e este app tem 30 controllers fazendo isso:
app/javascript/controllers/
application.js
nested_form_controller.js
tabs_controller.js
upload_progress_controller.js
welcome_modal_controller.js
auth/password_strength_controller.js
auth/password_visibility_controller.js
auth/recovery_codes_controller.js
auth/time_zone_controller.js
catalog/mermaid_controller.js
catalog/roadmap_path_controller.js
execution/editor_prefetch_controller.js
execution/hints_controller.js
execution/irb_controller.js
notes/filter_controller.js
ui/chart_controller.js
ui/clipboard_controller.js
ui/command_palette_controller.js
ui/confirmable_controller.js
ui/confirmation_controller.js
ui/country_picker_controller.js
ui/dialog_controller.js
ui/flash_controller.js
ui/inquiry_tier_controller.js
ui/locale_switch_controller.js
ui/mobile_sidebar_controller.js
ui/navbar_controller.js
ui/no_uploads_controller.js
ui/print_controller.js
ui/request_error_controller.js
ui/toggle_controller.js
Como todos são carregados, sem nenhuma linha de import à mão
app/javascript/controllers/index.js, completo:
import { application } from "controllers/application"
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
const isAdmin = document.body.dataset.admin === "true"
eagerLoadControllersFrom("controllers", application)
if (isAdmin) {
eagerLoadControllersFrom("admin_controllers", application)
}
eagerLoadControllersFrom("controllers", application) registra todo arquivo de controller dessa árvore de diretórios, então ninguém escreve uma linha import FlashController from "..." à mão. document.body.dataset.admin lê um atributo que você vai ver de novo: os dois layouts definem data-admin="<%= admin? %>" no <body>, então um segundo diretório de controllers, admin_controllers, só carrega numa sessão de admin.
Todo controller tem o mesmo formato
Todo arquivo acima começa com as mesmas duas linhas, como em app/javascript/controllers/ui/flash_controller.js:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
...
}
O que vai dentro do corpo dessa classe é o assunto deste curso. Targets nomeiam os elementos que um controller precisa alcançar (aula 3). Actions ligam um evento do DOM a um método do controller (aula 4). Values leem configuração tipada a partir de atributos data (aula 5). A aula 2 trata de algo que vem antes: como o caminho de um arquivo vira o identificador (ui--flash, auth--password-strength) que o HTML usa para se ligar a ele.
O que este curso cobre
Cada aula checa as próprias afirmações contra os controllers deste app e as views que os ligam. A aula 2 mostra como o caminho do arquivo de um controller vira o identificador do data-controller. A aula 3 trata de targets, com uma declaração static targets e os acessores que ela gera. A aula 4 trata de actions, tanto a sintaxe explícita event->controller#method quanto o atalho que deduz o evento. A aula 5 trata de values, incluindo um value tipado renderizado de uma constante Ruby para o HTML. A aula 6 mostra dois controllers independentes dividindo uma árvore de elementos. A aula 7 junta tudo num exemplo, com um pequeno desafio de código.
Continue com a aula 2
Nomeação: como um arquivo vira um identificador
Explica a regra fixa que transforma o caminho de um controller num identificador como auth--password-strength ou tabs.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.