Hello, Stimulus

Stimulus がどのように機能するかを学ぶ最良の方法は、簡単なコントローラを作ることです。この章ではその方法を紹介します。

原文 The best way to learn how Stimulus works is to build a simple controller. This chapter will show you how.

前提条件

手順を進めていくためにStimulus-starterプロジェクトのコピーを用意してください。こは、Stimulus を使うためにあらかじめ設定された白紙のアプリケーションです。

おすすめのやり方はGlitch上でstimulus-starterを編集することです。 何もインストールせずにブラウザ上で作業することができます。

Remix on Glitch

Glitchではなくテキストエディタで快適に作業したい場合は、Stimulus-starterを手元にcloneしてセットアップする必要があります:

$ git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn install
$ yarn start

その後、ブラウザで http://localhost:9000/ にアクセスしてみてください

(stimulus-starterプロジェクトは依存関係の管理にYarnパッケージ・マネージャーを使用しているので、最初にYarnパッケージ・マネージャーがインストールされていることを確認してください)

原文 Prerequisites To follow along, you’ll need a running copy of the stimulus-starter project, which is a preconfigured blank slate for exploring Stimulus.

We recommend remixing stimulus-starter on Glitch so you can work entirely in your browser without installing anything:

Remix on Glitch

Or, if you’d prefer to work from the comfort of your own text editor, you’ll need to clone and set up stimulus-starter:

$ git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn install
$ yarn start

Then visit http://localhost:9000/ in your browser.

(Note that the stimulus-starter project uses the Yarn package manager for dependency management, so make sure you have that installed first.)

すべての始まりはHTMLから

テキストフィールドとボタンを使った簡単な練習から始めましょう。ボタンをクリックすると、コンソールにテキストフィールドの値が表示されます。

すべてのStimulusプロジェクトはHTMLから始まります。public/index.htmlを開き、冒頭のタグの直後に以下のマークアップを追加します:

<div>
  <input type="text">
  <button>Greet</button>
</div>

ブラウザでページをリロードすると、テキストフィールドとボタンが表示されるはずです。

原文 Let’s begin with a simple exercise using a text field and a button. When you click the button, we’ll display the value of the text field in the console.

Every Stimulus project starts with HTML. Open public/index.html and add the following markup just after the opening tag:

<div>
  <input type="text">
  <button>Greet</button>
</div>

Reload the page in your browser and you should see the text field and button.

コントローラーでHTMLに命を吹き込む

Stimulusの最も重要なポイントはDOM 要素をJavaScript オブジェクトに自動的に接続することです。 これらのオブジェクトはコントローラと呼ばれます。

フレームワークの組み込みコントローラクラスを継承して、最初のコントローラを作成しましょう。src/controllers/ フォルダに hello_controller.js という名前の新しいファイルを作成します。そして、その中に以下のコードを記述します:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
}
原文 At its core, Stimulus’s purpose is to automatically connect DOM elements to JavaScript objects. Those objects are called controllers.

Let’s create our first controller by extending the framework’s built-in Controller class. Create a new file named hello_controller.js in the src/controllers/ folder. Then place the following code inside:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
}

コントローラとDOMをつなぐ識別子(identifier)

次に、このコントローラをどのようにHTMLに接続するかをStimulusに伝える必要があります。これを行うには、<div>data-controller属性に識別子を記述します:

<div data-controller="hello">
  <input type="text">
  <button>Greet</button>
</div>

識別子は要素とコントローラの間のリンクの役割を果たします。 この場合、識別子helloはStimulusにコントローラクラスのインスタンスをhello_controller.jsに作成するよう指示します。 コントローラの自動ロードの仕組みについては、インストールガイドを参照してください。

原文 Next, we need to tell Stimulus how this controller should be connected to our HTML. We do this by placing an identifier in the data-controller attribute on our `div`:
<div data-controller="hello">
  <input type="text">
  <button>Greet</button>
</div>

Identifiers serve as the link between elements and controllers. In this case, the identifier hello tells Stimulus to create an instance of the controller class in hello_controller.js. You can learn more about how automatic controller loading works in the Installation Guide.

これでうまくいっているのか?

ブラウザでページをリロードすると何も変わっていないことがわかります。 コントローラーが動作しているかどうかを知るにはどうすればいいのでしょうか?

一つの方法は、コントローラがドキュメントに接続されるたびにStimulusが呼び出すconnect() メソッドにconsole.logを記述することです。

hello_controller.jsconnect()メソッドを次のように実装します:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    console.log("Hello, Stimulus!", this.element)
  }
}

ページを再度読み込み、開発者コンソールを開いてください。「Hello, Stimulus!」と表示され、その後に <div> が表示されるはずです。

原文 Reload the page in your browser and you’ll see that nothing has changed. How do we know whether our controller is working or not?

One way is to put a log statement in the connect() method, which Stimulus calls each time a controller is connected to the document.

Implement the connect() method in hello_controller.js as follows:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    console.log("Hello, Stimulus!", this.element)
  }
}

Reload the page again and open the developer console. You should see Hello, Stimulus! followed by a representation of our div.

ActionはDOMイベントに反応する

それでは、「Greet」ボタンをクリックしたときにログが表示されるようにコードを変更する方法を見てみましょう。

まず、connect()の名前をgreete()に変更します:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  greet() {
    console.log("Hello, Stimulus!", this.element)
  }
}

ボタンのクリックイベントが発生したときにgreet() メソッドを呼び出したい。Stimulus では、イベントを処理するコントローラのメソッドをアクションメソッドと呼びます。

アクションメソッドをボタンのクリックイベントに接続するには、public/index.htmlを開き、ボタンにdata-action属性を追加します:

<div data-controller="hello">
  <input type="text">
  <button data-action="click->hello#greet">Greet</button>
</div>

アクションの記述子について

data-action属性の値であるclick->hello#greetはアクション記述子と呼びます。 この記述子は以下を表しています:

  • click はイベント名である
  • hello はコントローラの識別子である
  • greet は呼び出すアクションメソッドの名前である

ブラウザでページを読み込み、開発者コンソールを開いてください。Greet」ボタンをクリックすると、ログメッセージが表示されるはずです。

原文 Now let’s see how to change the code so our log message appears when we click the “Greet” button instead.

Start by renaming connect() to greet():

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  greet() {
    console.log("Hello, Stimulus!", this.element)
  }
}

We want to call the greet() method when the button’s click event is triggered. In Stimulus, controller methods which handle events are called action methods.

To connect our action method to the button’s click event, open public/index.html and add a data-action attribute to the button:

<div data-controller="hello">
  <input type="text">
  <button data-action="click->hello#greet">Greet</button>
</div>

﹟Action Descriptors Explained

The data-action value click->hello#greet is called an action descriptor. This particular descriptor says:

  • click is the event name
  • hello is the controller identifier
  • greet is the name of the method to invoke

Load the page in your browser and open the developer console. You should see the log message appear when you click the “Greet” button.

Targetsは重要な要素をコントローラのプロパティにマッピングする

テキストフィールドに入力した名前を使って「Hello, {名前}」と出力されるようにアクションを変更して、練習を終了します。

まずコントローラ内でinput要素を参照する必要があります。そして、valueプロパティを読み込んでその内容を取得します。

Stimulusでは、重要な要素をターゲットとしてマークすることができるので、対応するプロパティを通してコントローラ内で簡単に参照することができます。public/index.htmlを開き、input 要素にdata-hello-target属性を追加します:

<div data-controller="hello">
  <input data-hello-target="name" type="text">
  <button data-action="click->hello#greet">Greet</button>
</div>

次に、コントローラのターゲット定義のリストにnameを追加して、ターゲットのプロパティを作成します。 Stimulus は自動的にthis.nameTargetプロパティを作成し、最初にマッチしたターゲット要素を返します。このプロパティを使用して要素の値を読み取り、挨拶文の文字列を作成します。

やってみましょう。 hello_controller.jsを開き、次のように更新します:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

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

  greet() {
    const element = this.nameTarget
    const name = element.value
    console.log(`Hello, ${name}!`)
  }
}

次にブラウザでページをリロードし、開発者コンソールを開きます。 入力フィールドにあなたの名前を入力し、「Greet」ボタンをクリックしてください。 Hello world!

原文

We’ll finish the exercise by changing our action to say hello to whatever name we’ve typed in the text field.

In order to do that, first we need a reference to the input element inside our controller. Then we can read the value property to get its contents.

Stimulus lets us mark important elements as targets so we can easily reference them in the controller through corresponding properties. Open public/index.html and add a data-hello-target attribute to the input element:

<div data-controller="hello">
  <input data-hello-target="name" type="text">
  <button data-action="click->hello#greet">Greet</button>
</div>

Next, we’ll create a property for the target by adding name to our controller’s list of target definitions. Stimulus will automatically create a this.nameTarget property which returns the first matching target element. We can use this property to read the element’s value and build our greeting string.

Let’s try it out. Open hello_controller.js and update it like so:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

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

  greet() {
    const element = this.nameTarget
    const name = element.value
    console.log(`Hello, ${name}!`)
  }
}

Then reload the page in your browser and open the developer console. Enter your name in the input field and click the “Greet” button. Hello, world!

コントローラをよりシンプルに

StimulusコントローラはJavaScriptのクラスのインスタンスであり、そのメソッドはイベントハンドラとして動作します。

つまり、標準的なリファクタリングテクニックを自由に使えるということです。 例えば、入力された名前を返すname getter を作ることでgreet()メソッドをすっきりさせることができます:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

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

  greet() {
    console.log(`Hello, ${this.name}!`)
  }

  get name() {
    return this.nameTarget.value
  }
}
原文 We’ve seen that Stimulus controllers are instances of JavaScript classes whose methods can act as event handlers.

That means we have an arsenal of standard refactoring techniques at our disposal. For example, we can clean up our greet() method by extracting a name getter:

// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

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

  greet() {
    console.log(`Hello, ${this.name}!`)
  }

  get name() {
    return this.nameTarget.value
  }
}

おさらいと次のステップ

おめでとう! あなたにとって最初のStimulusコントローラを書くことができました!

ここではフレームワークの最も重要な概念であるコントローラ、アクション、ターゲットについて説明しました。 次の章では、これらを組み合わせて、実際にBasecampから抽出したコントローラを作ってみましょう。

原文 Congratulations—you’ve just written your first Stimulus controller!

We’ve covered the framework’s most important concepts: controllers, actions, and targets. In the next chapter, we’ll see how to put those together to build a real-life controller taken right from Basecamp.