Múltiplos controllers, um elemento
O data-controller não se limita a um identificador. Escreva dois, separados por espaço, e os dois controllers se conectam ao mesmo elemento de forma independente, cada um com seus próprios targets, values e ciclo de vida. Nenhum sabe que o outro existe, a menos que algo os conecte explicitamente. A UI de desafio real desta aplicação, o editor Ruby da aula de desafio deste próprio curso, faz isso.
Dois controllers reais compartilhando um elemento
A tag de abertura do bloco de desafio em app/views/catalog/lessons/show.html.erb:
<div class="mt-16 pt-12 border-t border-subtle"
data-controller="execution--irb execution--hints"
data-action="execution--irb:failed->execution--hints#attemptFailed"
data-execution--irb-challenge-id-value="<%= @challenge.id %>"
data-execution--hints-url-value="<%= execution_api_v1_challenge_solution_path(@challenge) %>"
data-execution--hints-failed-attempts-value="<%= @failed_attempts %>"
data-execution--hints-required-attempts-value="<%= Execution::SolutionAccessPolicy::REQUIRED_FAILED_ATTEMPTS %>"
data-execution--hints-revealed-value="<%= @solution_revealed %>">
Essa linha data-action é a ligação entre os dois controllers. Como ela funciona é assunto da aula 4. Por ora, note só que ela é real, está nesse mesmo elemento, e nenhum dos dois controllers precisou ser avisado dela. Um <div> leva dois identificadores de controller no data-controller: execution--irb e execution--hints. O Stimulus instancia os dois sobre este mesmo elemento. O execution--irb ganha seu próprio this.element (essa div), e o execution--hints também: o mesmo nó do DOM, duas instâncias de controller separadas, sem relação entre si por padrão.
Cada controller lê só os próprios values
Os atributos de value têm o prefixo de cada controller: data-execution--irb-challenge-id-value pertence ao execution--irb, e data-execution--hints-failed-attempts-value pertence ao execution--hints. O curso "StimulusJS: values/classes" mostrou como o nome do atributo HTML de um value vem do identificador do seu controller. É por isso que dois controllers podem dividir um elemento sem que seus values colidam. O value challengeId do execution--irb e o value url do execution--hints ficam em atributos com prefixos diferentes na mesma tag, e cada controller ignora as declarações do outro.
Por que colocá-los no mesmo elemento
O execution--irb roda o código do estudante no navegador, em ruby.wasm, como prévia, e depois o envia. A nota vem do servidor, e é por esse veredito que o controller sabe se a tentativa passou ou falhou. O execution--hints cuida da revelação de dicas e da trava da solução, a mecânica de "dicas liberadas após tentativas falhas" que um estudante vê na aula de desafio deste próprio curso. São duas responsabilidades separadas, e dividi-las em dois controllers deixa cada um pequeno. O execution--irb nunca mexe no DOM das dicas, e o execution--hints nunca roda nem envia código. Dividir um elemento é o que torna possível o mecanismo da aula 4. Um evento disparado a partir do this.element de um controller alcança qualquer coisa que escute nesse mesmo elemento, então não é preciso um broadcast global quando os dois controllers vivem no mesmo nó.
Pontos-chave
- O
data-controlleraceita vários identificadores separados por espaço; cada um ganha sua própria instância de controller, independente, conectada ao mesmo elemento. - A UI de desafio real desta aplicação (
show.html.erb) conectaexecution--irbeexecution--hintsao mesmo<div>, o elemento por trás do desafio deste próprio curso. - Os atributos de
static valuesde cada controller continuam com o prefixo do próprio identificador, então dois controllers num elemento nunca colidem nos nomes de atributo. - Separar o
execution--irb(roda o código) doexecution--hints(UI de dicas e solução) mantém estreita a responsabilidade de cada controller, mesmo com os dois agindo sobre um elemento compartilhado.
Continue com a aula 2
this.dispatch(): os próprios eventos customizados de um controller
Como o método herdado dispatch() dispara eventos customizados, com defaults para alvo, detail, propagação e prefixo.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.