O básico de Stimulus em Rails
Tags: rails, stimulus
Published: 2022-12-15 21:53:02

Talvez você tenha se perguntado a existência da gem `stimulus` que Rails instala por padrão, mas não se preocupe, que aqui você vai aprender sobre ele.

**Observação: Esse post é necessário que tenha um conhecimento DOM. Se não, pode ser complicado em entender.**

## O que é Stimulus?

Eu vou traduzir a documentação, pois, sinceramente, não consigo explicar isso em outras palavras.

Stimulus é um framework Javascript com ambições modesta.
Ao contrário de outros frameworks front-end, Stimulus é projetado para aprimorar HTML estático ou renderizado pelo servidor - o "HTML que você possui" - conectando objetos Javascript a elementos da página usando anotações simples.

Esses objetos JavaScript são chamados de controllers, e o Stimulus monitora continuamente a página esperando que os atributos `data-controller` apareçam no HTML. Para cada atributo, o Stimulus examina o valor do atributo para encontrar uma classe controller correspondente, cria uma nova instância dessa classe e a conecta ao elemento.

Você pode pensar desta maneira: Assim como o atributo `class` é uma ponte que conecta HTML a CSS, o atributo `data-controller` do Stimulus é uma ponte que conecta HTML a Javascript

Além dos controllers, os outros três principais conceitos de Stimulus são:

- `actions`, que conectam métodos do controller a eventos DOM usando atributos `data-action`;
- `targets`, que localizam elementos de significado dentro de um controller;
- `values`, que leem, escrevem e observam atributos de dados no elemento do controller.

O uso de atributos de dados pelo Stimulus ajuda a separar o conteúdo do comportamento da mesma forma que o CSS separa o conteúdo da apresentação. Além disso, as convenções do Stimulus naturalmente encorajam você a agrupar códigos relacionados por nome.

Por sua vez, o Stimulus ajuda você a criar controllers pequenos e reutilizáveis, fornecendo estrutura suficiente para evitar que seu código se transforme em uma “sopa de JavaScript”.

Talvez, com essa explicação, você não tenha entendido muito, então vamos para a prática para fixar isso.

## Prática

Eu estava pensando que tipo de aplicação eu criaria para isso, porém, não consegui em pensar em nada. Então vai ser uma aplicação aleatória que possa aproveitar o máximo do Stimulus.

Então, execute os comandos abaixo para preparar o terreno.

```bash
rails new exemplo_stimulus
cd exemplo_stimulus
rails g controller Pagina index
```
Abra o arquivo `config/routes.rb`.

```ruby
# config/routes.rb
Rails.application.routes.draw do
  root 'pagina#index'
end
```

Agora, o nosso terreno está pronto.

## Controllers

Vá no arquivo `app/views/pagina/index.html.erb` e adicione o código abaixo.

```erb
<!-- app/views/pagina/index.html.erb -->
<div data-controller="hello"></div>
```

Rode o servidor e vá para URL `localhost:3000` e veja a mágica acontecer.

Viu, apareceu o "Hello world!", mas como?

Antes de explicar, o que aconteceu, vamos, primeiro, entender sobre o atributo `data-controller`.

Como foi explicado lá em cima, que o Stimulus procura no html pelo o atributo `data-controller` para criar uma instância de classe e conectar com o elemento.

Só que a dúvida é, onde está essa classe?

Bem, na sua aplicação, procure o arquivo no diretório `app/javascript/controllers` e verá ele lá.

Achou? E qual é o nome do arquivo?

`hello_controller.js` é o nome do arquivo, ou seja, o Stimulus vai usar o valor do atributo para procurar um arquivo do diretório `app/javascript/controllers`.

Vamos fazer um teste, mude o valor do `data-controller`.

```erb
<!-- app/views/pagina/index.html.erb -->
<div data-controller="ola"></div>
```

Agora, reinicie a página e verá ...

Nada, obviamente, esperava o que?

Bem, por que não apereceu nada?

É que Stimulus está procurando um arquivo com nome `ola_controller.js` e esse arquivo não existe.

Então, vamos mudar o nome do arquivo `hello_controller.js` para `ola_controller.js` e reinicie a página.

Agora, funcionou.

Uma observação, é necessário que tenha o nome `_controller.js` no final do arquivo.

Bem, eu acho que você sacou como que funciona o `data-controller`.

Agora, vamos abrir o `app/javascript/controllers/ola_controller` e observar ele.

```javascript
// app/javascript/controllers/ola_controller
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    this.element.textContent = "Hello World!"
  }
}
```

Não tem muito segredo nesse arquivo, então eu vou só explicar o método `connect`, pois o resto dá para entender de boa.

O método `connect` é executado, quando usar o atributo `data-controller`.

Beleza, agora vamos nos aprofundar um pouco.

## Actions

Vá para o arquivo `app/views/pagina/index.html.erb` e coloque o código abaixo.

```erb
<!-- app/views/pagina/index.html.erb -->
<div data-controller="ola">
  <input type="text" data-action="keyup->ola#mudarTexto">
  <p></p>
</div>
```

Ok, nós temos um novo atributo.

O `data-action` serve para lida com evento DOM do seu controller.

Vamos observar o valor do nosso atributo `data-action`.

Observando ele, você pode notar um padrão, que é, começa com evento DOM `keyup` e vai para o controller `ola` e execute o método `mudarTexto`.

Ou seja, é desse jeito o padrão `evento->controller#método`.

Não tem muito mistério sobre isso, basta lembrar desse padrão.

Então vamos para o arquivo `app/javascript/controllers/ola_controller.js` e colocar o novo método e remover o `connect`.

```javascript
// app/javascript/controllers/ola_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  mudarTexto(event) {
    console.log(event.target.value);
  }
}
```

Pronto, reinicie a página e abra o dev tools para ver o console.

Viu, ele está imprimindo o valor do input.

Você pode pensar, nossa, que simples.

Sim, de fato, é muito simples.

Agora vamos mergulhar mais, que já estamos quase no fim.

## Targets

Novamente, edite o arquivo, `app/views/pagina/index.html.erb`.

```erb
<!-- app/views/pagina/index.html.erb -->
<div data-controller="ola">
  <input type="text" data-action="keyup->ola#mudarTexto">
  <p data-ola-target="texto"></p>
</div>
```

Hum, um outro atributo.

Esse atributo é bem diferente, se prestar atenção, você pode ver o nome do controller no meio, ou seja, para usar ele, tem que seguir esse padrão, `data-nome_do_controller-target`.

Mas a questão é, o que ele faz?

Como o nome diz, ele é um alvo do controller. 

O uso dele seria equivalente a `GetElementById`, só que mais simples.

Vamos para o arquivo `app/javascript/controllers/ola_controller.js`.

```javascript
// app/javascript/controllers/ola_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "texto" ]

  mudarTexto(event) {
    this.textoTarget.textContent = `olá, ${event.target.value}`
  }
}
```

Pode notar que existe uma variável `targets`, em que, está atribuindo um array com um valor `"texto"`, ou seja, tem ter o valor igual, onde foi posto no HTML.

Agora, se você observar o `this.textoTarget`, ele é o elemento, a qual você colocou o atributo `data-ola-target`.

Então reinicie a página, e veja a mágica acontecer.

## Values

O último conceito do Stimulus, então, abra o arquivo index novamente.

```erb
<!-- app/views/pagina/index.html.erb -->
<div data-controller="ola" data-ola-nome-value="Zulano" >
  <input type="text" data-action="keyup->ola#mudarTexto">
  <p data-ola-target="texto"></p>
</div>
```

Beleza, antes de explicar esse atributo, vamos primeiro para o arquivo javascript.

```javascript
// app/javascript/controllers/ola_controller.js.
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "texto" ]
  static values = {
    nome: String
  }

  mudarTexto(event) {
    console.log(this.nomeValue)
    this.textoTarget.textContent = `olá, ${event.target.value}`
  }
}
```

Pode notar que ele meio que equivalente ao target, o que muda é que o targets aceita um array, enquanto o values é um JSON.

O padrão do atributo é `data-nome_do_controller-chave-value`.

Novamente, reinicie a página e veja o console do dev tools.

Bem, eu vou acabar por aqui, isso é o básico do Stimulus.
 
Eu sinto que esse post foi um desastre, mas se houver qualquer dúvida, pode comentar que vou responder.

Bem, então é isso, tchau!