##まずは前々回の復習がてら
ハンドブックにある「Hello, Stimulus」を若干書き換えて、ボタンを押すと「A」「B」に入力した文字が「C」に表示されるようにしてみた。
<div data-controller="test-desu">
A :<input data-target="test-desu.name_1" type="text">
<button data-action="click->test-desu#greet" >Greet</button>
B :<input data-target="test-desu.name_2" type="text">
<label data-target="test-desu.write_here">C :write here</label>
</div>
↓できた画面が、こちら。
ターゲット名「name_1」→A行の入力枠
ターゲット名「name_2」→B行の入力枠
ターゲット名「write_here」→"C:write here"の部分
これに対してstimulusのjsで、(ファイル名=thmlで振ったデータコントローラー名……なお名称については気にしない方向で(「てすと_です」って……いや、他にぱっと思いつかなかったんだ))
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "name_1","name_2","write_here" ]
greet() {
this.write_hereTarget.textContent = this.name + "。そして、" + this.name2;
}
get name() {
return this.name_1Target.value
}
get name2() {
return this.name_2Target.value
}
}
「A」「B」に入力してボタンを押すと……
ターゲット名は、
【実際に使う部分……「name_1Target」「this.name_2Target」「write_hereTarget」】
だけでなく、
【初めの宣言……「static targets = [ "name_1","name_2","write_here" ]」】
にも記述しなければいけないことに注意
なお、
・static targets = [ "name_1" ]
・static targets = [ "name_2" ]
・static targets = [ "write_here" ]
と分けて書いたりすると、エラーになる(当たり前かもしれないけど、実際自分はこう書いてエラーを出しました orz。
##ではもし、「A」の部分が複数あったら?
つまり、
<div data-controller="test-desu">
<div>
A-1 :<input data-target="test-desu.name_1" type="text">
<button data-action="click->test-desu#greet" >Greet-1</button>
</div>
<div>
A-2 :<input data-target="test-desu.name_1" type="text" >
<button data-action="click->test-desu#greet" >Greet-2</button>
</div>
<div>
A-3 :<input data-target="test-desu.name_1" type="text" >
<button data-action="click->test-desu#greet" >Greet-3</button>
</div>
B :<input data-target="test-desu.name_2" type="text">
<label data-target="test-desu.write_here">C :write here</label>
</div>
これで、「A1〜3のうち、押したボタンの行内容」+「Bの内容」が「Cの部分」に表示されるようにしたい。
なおハンドブックの4にあるように、同名のターゲットを複数用意することは可能。その場合、「Target」ではなく「Targets」を使用する……はず。
なので試しに、jsを止めて検証ツールで見てみると、
「this.name_1Targets(番号)」で、行情報を取得できる。
また
「 greet() {」→→→「 greet(el) {」
と変更すれば、
「el.target.dataset」で、アクションを発生させたボタンの情報を取得できる。
本当はここで「.index」とかして、【複数あるgreetアクションのうち、何番目が刺激されたのか】を取得したかったのだけど……見つからなくって諦めて(ありそうな気はしているので、「何番目の要素か」の取得方法、ご存知の方がいれば教えてください)、html側に「何番目の要素か」を取得するための「data-」要素を追加することにした。
具体的には、
【data-greet-num = "0〜2の数字"】
を追加記述。これでjs側に番号を渡し、jsでは
el.target.dataset.greetNum
で受け取ってやることにする。
つまり、、、、
<div data-controller="test-desu">
<div>
A-1 :<input data-target="test-desu.name_1" type="text">
<button data-action="click->test-desu#greet" data-greet-num = "0" >Greet-1</button>
</div>
<div>
A-2 :<input data-target="test-desu.name_1" type="text">
<button data-action="click->test-desu#greet" data-greet-num = "1" >Greet-2</button>
</div>
<div>
A-3 :<input data-target="test-desu.name_1" type="text">
<button data-action="click->test-desu#greet" data-greet-num = "2" >Greet-3</button>
</div>
B :<input data-target="test-desu.name_2" type="text">
<label data-target="test-desu.write_here">C :write here</label>
</div>
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "name_1","name_2","write_here" ]
greet(el) {
this.write_hereTarget.textContent =
this.name_1Targets[el.target.dataset.greetNum].value +
"。そして、" + this.name_2Target.value;
}
// ↓「name」に「el」を渡せなかったため、関数自体を取り消して「greet(el)」に纏めた
// get name(el) {
// return this.name_1Targets[el.target.dataset.greetNum].value
// }
// get name2() {
// return this.name_2Target.value
// }
}
#さらに応用
< data-greet-num = "数字" >
の数字番号は、ただ0から順番に振っているだけ。
だから当然、【一覧画面、検索されたデータを「モデル名.each do」で回して一行ずつ表示】している部分にも簡単に当てることができる。
以下は、【「cd」と「name」の列を持つuser情報の一覧画面(scaffoldで作成)】に追記したもの
<h1>Users</h1>
<div data-controller="greet-user">
<table>
<thead>
<tr>
<th>Cd</th>
<th>Name</th>
<th colspan="4"></th>
</tr>
</thead>
<tbody >
<% @users.each_with_index do |user,i| %>
<tr>
<td><%= user.cd %></td>
<td data-target="greet-user.name" ><%= user.name %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<td><button data-action="click->greet-user#greet" data-greet-num = <%= i.to_s %> >Greet</button></td>
</tr>
<% end %>
</tbody>
</table>
<label data-target="greet-user.write_here">write here</label>
</div>
<br>
<%= link_to 'New User', new_user_path %>
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "name","write_here" ]
greet(el) {
this.write_hereTarget.textContent =
this.nameTargets[el.target.dataset.greetNum].textContent +
"さん、こんにちは。" ;
}
}
ボタンを押すと、
【選択した行の「Name」 + "さん、こんにちは。"】が表示される。
うん、少しずつではあるが、stimulusの使い方がつかめてきた気がする。