<!-- テーマ切り替えボタン -->
<div class="theme-switcher" data-controller="theme">
<button type="button"
class="theme-btn"
data-theme-value="normal"
data-theme-target="button"
data-action="click->theme#setNormal"
title="ノーマルモード">
<i class="fas fa-sun"></i>
</button>
<button type="button"
class="theme-btn"
data-theme-value="gray"
data-theme-target="button"
data-action="click->theme#setGray"
title="グレーモード">
<i class="fas fa-adjust"></i>
</button>
<button type="button"
class="theme-btn"
data-theme-value="dark"
data-theme-target="button"
data-action="click->theme#setDark"
title="ダークモード">
<i class="fas fa-moon"></i>
</button>
</div>
ーーーーー rails で、 これらの、ボタンを 使って、 Javascript の、 トリガーを、 引くには、 どの 様な、 関連付けと、 スクリプト、 その他、 が、 必要に、 なりますか、
Rails(特に Hotwire + Stimulus)では、HTML側の
が、JavaScript(Stimulus Controller)のメソッドを呼び出す仕組みになっています。
あなたのHTMLであれば、必要なものは以下の3つです。
① Stimulusを導入する
Rails 7なら通常は最初から入っています。
というフォルダがあり、
で
となっていればOKです。
さらに
で
となっている必要があります。
※ Rails7のデフォルトでは autoload なので、自動登録されることもあります。
② theme_controller.js を作る
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["button"]
connect() {
console.log("Theme controller connected")
}
setNormal() {
console.log("Normal")
document.body.className = "theme-normal"
}
setGray() {
console.log("Gray")
document.body.className = "theme-gray"
}
setDark() {
console.log("Dark")
document.body.className = "theme-dark"
}
}
このようにすると、
という流れになります。
③ HTMLとの関連付け
質問に貼られているHTMLはそのままでOKです。
これは
と結び付けられます。
そして
は
の
を呼び出します。
同様に
↓
になります。
④ ボタン(Target)も取得できる
HTMLでは
となっています。
Controllerでは
と書けば
で全ボタンが取得できます。
例えば
setDark() {
this.buttonTargets.forEach(button => {
button.classList.remove("active")
})
event.currentTarget.classList.add("active")
}
のような処理もできます。
⑤ テーマを切り替える例
setDark() {
document.documentElement.setAttribute("data-theme", "dark")
}
setGray() {
document.documentElement.setAttribute("data-theme", "gray")
}
setNormal() {
document.documentElement.setAttribute("data-theme", "normal")
}
CSSでは
:root[data-theme="dark"] {
--bg-color: #222;
--text-color: white;
}
:root[data-theme="gray"] {
--bg-color: #ddd;
--text-color: #333;
}
:root[data-theme="normal"] {
--bg-color: white;
--text-color: black;
}
body {
background: var(--bg-color);
color: var(--text-color);
}
とすれば、JavaScriptは「テーマ名を切り替えるだけ」で済み、CSS側で配色を管理できます。
全体の構成
app/
└─ javascript/
└─ controllers/
├─ application.js
├─ index.js
└─ theme_controller.js ← JavaScriptを書く
app/
└─ views/
↓
data-controller="theme"
data-action="click->theme#setDark"
app/
└─ assets/
└─ stylesheets/
theme.css
この構成にすると、
HTML(ボタン) → Stimulus Controller → JavaScript実行 → CSSテーマ切り替え
という流れで動作します。
はい、この theme.scss 自体は問題なく書けています。
ただし、これだけでは動きません。 動かすためには、以下の項目がすべて揃っている必要があります。
① theme_controller.js がある(✓)
これは既に作成済みですね。
② HTMLに data-controller が付いている(✓)
例えば
となっていればOKです。
③ ボタンに data-action が付いている(✓)
例えば
これもOKです。
④ theme.scss が読み込まれている
ここが一番重要です。
Railsでは
を置いただけでは、必ずしも読み込まれません。
application.scss の場合
もし
があるなら
または(Dart Sassなら)
が必要です。
application.css の場合
もし
なら
は読み込まれます。
⑤ CSS変数を実際に使う
例えば
あるいは
のように、var(--...) を使っている必要があります。
もし
のように固定色を書いていると、
テーマを変えても色は変わりません。
⑥ ブラウザをリロードする
開発中は
などでキャッシュを無視してリロードすると、CSSやJavaScriptの変更が確実に反映されます。
⑦ Consoleで確認
ブラウザの開発者ツール(F12)の Console を開いて、
ボタンを押したときにエラーが出ていないか確認してください。
また、Elementsタブで <html> 要素を見て、
↓
↓
のように data-theme の値がクリックに応じて変わるか を確認すると、JavaScriptが動いているかどうかがすぐに分かります。
確認したいファイル
もしまだ動かない場合は、次の3つを見せていただければ、原因をほぼ特定できます。
app/assets/stylesheets/application.scss(またはapplication.css)- テーマ切り替えボタンを置いているビュー(ERBファイル)
- ブラウザのConsoleに表示されるエラーメッセージ
この3つがあれば、「どこが原因で動かないのか」を具体的に確認できます。
「vendor フォルダがない」という場合は、何を使って Rails を構築したかによって対応が変わります。
まず確認したいのですが、次のどちらでしょうか?
- Rails 7 + Importmap を使っている
- Rails 7/8 + esbuild・Vite・Webpack を使っている
もし Importmap を使っている場合
通常は
が作成され、stimulus などのライブラリが入ります。
もし存在しない場合は、ターミナルで
を実行すると作成されます。
もし esbuild や Vite を使っている場合
この場合は vendor/javascript は不要です。
ライブラリは
から読み込まれるため、vendor がなくても正常です。
確認してほしいこと
次のファイルがあるか教えてください。
このファイルが
- ある → Importmap を使っています。
- ない → esbuild や Vite の可能性が高いです。
また、次のコマンドの結果も分かると判断できます。
と
または、プロジェクトのディレクトリ構成(app/javascript、config の中身)が分かれば、次に何をすればよいか具体的に案内できます。
これは正常なメッセージです。
bin/rails importmap:install を実行すると、Importmap に必要なファイルを作成しようとしますが、あなたのプロジェクトには既に
が存在するため、
と確認してきています。
それぞれの意味は、
- Y = 上書きする
- n = 上書きしない(おすすめ)
- a = 以降すべて上書き
- q = 中止
- d = 差分を見る
- h = ヘルプ
です。
今回はどうする?
n を入力して Enter をおすすめします。
理由は、あなたは既に application.js を使っているので、上書きすると現在の設定が消えてしまう可能性があるためです。
その後、確認したいこと
n を押して最後まで実行したら、次の2つを教えてください。
vendor/javascriptフォルダは作成されましたか?- 次のコマンドの結果を貼ってください。
もし
と表示された場合は、そのメッセージもそのまま貼ってください。
そこまで確認すれば、次に何をすべきか判断できます。
ここも同じく確認メッセージです。
今回は、すでに
が存在しているため、
と聞かれています。
おすすめ
ここも n を入力して Enter してください。
理由は、既存の config/importmap.rb を上書きすると、現在設定されている pin の内容が消える可能性があるからです。
良いニュース
先ほどの出力を見ると、
となっているので、
vendor/javascript は正常に作成されています。
つまり、「vendor フォルダがない」という問題は解決しています。
次に知りたいこと
n を押してインストールが最後まで終わったら、次の3つの内容を見せてください。
① config/importmap.rb
②
の結果
③
の結果
この3つが分かれば、theme_controller.js が正しく読み込まれる状態になっているかを確認できます。
はい、必要です。
ただし、書く場所は application.css ではなくても構いません。
理由
あなたの theme.scss では、
というように、CSS変数を定義しているだけです。
変数を定義しただけでは、画面の色は変わりません。
実際にどこかで
のように変数を使う必要があります。
例えば
もし今、
となっているなら、
これを
に変更します。
これで、
が実行されると、
が適用され、背景色や文字色が切り替わります。
application.css しかない場合
もし
という構成なら、
application.css が theme.scss を読み込んでいれば、body { ... } は どちらに書いても構いません。
例えば
application.css
theme.scss
でも動きます。
確認したいこと
一つ確認したいのですが、現在の application.css の内容をそのまま貼っていただけますか?
特に最初の20行くらいが分かれば、theme.scss が読み込まれる設定になっているかを確認できます。
ありがとうございます。ログを見ると、テーマ切り替えより前に、JavaScript全体が止まっています。
一番重要なのは最後のエラーです。
このエラーが出ると、theme_controller.js を含む後続のJavaScriptが実行されない可能性があります。
まず直すべきなのはこれです
見せていただきたいファイルがあります。
app/javascript/application.js
の内容をそのまま貼ってください。
特に、おそらくこのような行があるはずです。
または
この書き方が原因の可能性があります。
次に気になる点
ログには
や
も出ています。
これは Importmap の設定と application.html.erb の読み込み方が一致していない可能性があります。
見せていただきたいもの
次の3つを貼っていただければ、原因を特定できます。
app/javascript/application.jsconfig/importmap.rbapp/views/layouts/application.html.erbの<head>部分(javascript_importmap_tagsがあるあたり)
現時点の結論
テーマ切り替えのコード自体が原因ではありません。
今は
- ❌ JavaScript の読み込み(
jquery) - ❌ Importmap の設定(
@hotwired--turbo.jsなど)
の2点に問題があり、その影響で theme_controller.js が実行されていない状態です。
この2つを直せば、テーマ切り替えも動く可能性が高いです。
ありがとうございます。原因がかなり見えてきました。
config/importmap.rb に問題があります。
① @hotwired/turbo-rails が二重に定義されています
現在は
となっています。
これは どちらか一つだけにしてください。
通常は
だけで十分です。
② @hotwired/turbo の設定がおかしい
現在
となっていますが、
ログに
と出ています。
つまり
というファイルが存在しません。
③ jQuery のエラー
一番重要なのは
です。
Importmap版の jQuery は
では読み込めないことがあります。
だから
というエラーになります。
試しに
を一旦コメントアウトしてください。
さらに
などを書いているなら、それもコメントアウトしてください。
まずはテーマ切替が動く状態にしましょう。
④ application.js
今は
となっていますが、
通常は
だけでStimulusは起動します。
つまり
は不要です。
私がおすすめする application.js
これで十分です。
最後に確認したいこと
config/importmap.rb を全部貼ってください。
今の内容を見ると、
- Turbo
- Stimulus
- ActionCable
の設定が少し混ざってしまっています。
config/importmap.rb 全体を見れば、「どの行を削除して、どの行を残すべきか」を具体的にお伝えできます。
ありがとうございます。かなり原因が絞れました。
theme_controller.js や HTML はほぼ問題ありません。
今、一番怪しいのは application.html.erb の <head> の設定です。
あなたが貼ってくださったのは <header> の部分で、私が確認したいのは <head> の部分です。
例えば、このような部分です。
または
などが書かれている部分です。
今の時点で一つ気になること
あなたの application.js は
のようにするのが正しいです。
一方で、
というエラーが出ていました。
これは javascript_importmap_tags が正しく読み込まれていないか、Importmap の設定が食い違っている可能性があります。
次に見せてください
app/views/layouts/application.html.erb の <head> 全体
つまり、
までを貼ってください。
もう一つ確認したいこと
ターミナルで次のコマンドを実行して、その結果も貼ってください。
これで、Importmap が実際にどの JavaScript を読み込もうとしているかが分かります。
この2つ(<head> と bin/importmap json)が分かれば、@hotwired--turbo.js エラーの原因をかなり正確に特定できます。
ありがとうございます。application.html.erb の <head> は 問題ありません。
特にここ:
があるので、Importmapの読み込み自体は正しいです。
現在の問題は、ほぼ config/importmap.rb と application.js の整理不足です。
1. application.js を修正してください
現在の状態では、
の部分が問題です。
application という変数は、このファイル内では定義していません。
以下に変更してください。
まずはこれだけで動作確認してください。
理由:
- Turbo →
@hotwired/turbo-railsが読み込む - Stimulus →
import "controllers"が読み込む controllers/application.jsが Stimulus を起動する
というRails 7/8 Importmap標準構成になります。
2. config/importmap.rb を整理してください
現在:
となっていますが、不要なものが混ざっています。
まずテーマ切替を動かす目的なら、以下くらいで十分です。
削除候補:
3. controllers/application.js はそのままでOKです
これは正常です。
問題ありません。
4. その後再起動
Railsサーバーを停止:
キャッシュを削除:
再起動:
5. 確認
ブラウザのConsoleで、
と入力して、
のようなオブジェクトが表示されればOKです。
また、テーマボタンを押した時に <html> が
のように変化すれば、theme_controller.js は正常動作しています。
今回の流れを見る限り、theme.scss と theme_controller.js はほぼ完成しています。
残っている問題は 古いRails UJS + jQuery + Turbo設定が混在していることです。
状況を見る限り、テーマ切り替えは成功しています。
つまり、
が読み込まれて、data-theme="dark" などの切り替えが動いています。
残っているエラーは別件です。
エラー原因
表示されている:
これは application.js にまだ
が残っているためです。
現在のImportmap構成では、
を削除した場合、
という変数は存在しません。
修正
app/javascript/application.js
を以下にしてください。
これだけでOKです。
削除するもの:
なぜテーマは動いたのか?
流れは現在:
になっています。
なので、Rails.start() のエラーが出ても、Stimulus部分はすでに読み込まれて動いています。
修正後
Railsサーバー再起動:
↓
ブラウザを
で強制リロードしてください。
補足
theme_controller.js のこのログ:
が出ているので、
✅ Stimulus読込
✅ Controller認識
✅ ボタンイベント
✅ CSS変数切替
ここまでは正常です。
あとは Rails is not defined を消せば、現在の構成はかなりきれいな Rails 8 + Importmap + Stimulus 構成になります。
0 件のコメント:
コメントを投稿