2002421taiga
@2002421taiga (max 410)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

railsのwebpackを用いてJSが読み込めない

解決したいこと

railsでjavascriptが適応できない(webpackを使っています)
application.html.erbにhome/top.jsを読み込みたいです。
home/top.jsはwebpackで読み込むためにapp/javascriptの配下に置いています。

発生している問題・エラー(console)

top.js:14 Uncaught TypeError: Cannot read properties of null (reading 'querySelector')
    at PhotoViewer.updatePhotoViewer (top.js:14:1)
    at PhotoViewer.init (top.js:9:1)
    at Object../app/javascript/home/top.js (top.js:59:1)
    at __webpack_require__ (bootstrap:19:1)
    at Module../app/javascript/packs/application.js (application.js:10:1)
    at __webpack_require__ (bootstrap:19:1)
    at bootstrap:83:1
    at bootstrap:83:1

該当するソースコード

app/views/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>インスタ</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class='header'>
      <% if user_signed_in? %>
        <ul>
          <li><%= link_to 'インスタ' ,kakomons_path %></li>
          <li></li>
        </ul>
      <% else %>
        <ul>
          <li><%= link_to 'インスタ' ,root_path,class:'aokako-font' %></li>
          <li class='top'><%= link_to 'ログイン' ,new_user_session_path,class:'login-font' %></li>
          <li><%= link_to '新規登録',new_user_registration_path,class:'signin-font' %></li>
        </ul>
      <% end %>
    </div>

    <%= yield %>
  </body>
</html>
app/javascript/packs/application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start();
require("turbolinks").start();
require("@rails/activestorage").start();
require("channels");
require("home/top");

import "jquery";
import "popper.js";
import "bootstrap";
import "../stylesheets/application";
import "../stylesheets/homes";


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)
app/views/home/top.html.erb
<div id="top">
  <div class="frame">
  </div>
</div>
app/javascript/home/top.js
class PhotoViewer {
    constructor(rootElm,images){
        this.rootElm = rootElm;
        this.images = images;
        this.currentIndex = 0;
    }

    init(){
        this.updatePhotoViewer();
    }

    updatePhotoViewer() {
        const frameElm = this.rootElm.querySelector('.frame');
        const image = this.images[this.currentIndex];
        frameElm.innerHTML = `
            <div class="image">
                <img src="${image}">
            </div>
        `;

        this.startTimer();
    }

    next(){
        const lastIndex = this.images.length - 1;
        if(this.currentIndex === lastIndex) {
            this.currentIndex = 0
        } else {
            this.currentIndex++;
        }
        this.updatePhotoViewer();
    }

    startTimer() {
        if(this.timerKey) {
            clearTimeout(this.timerKey)
        }

        this.timerKey = setTimeout(()=>{
            this.next();
        },6000);
    }

}

/*global images*/
// eslint-disable-next-line no-native-reassign
images = [
 'assets/images/img.jpeg',
];
new PhotoViewer(document.getElementById('top'),images).init();

自分で試したこと(2つあります)

①app/javascript/にhome/top.jsを作り、
app/javascript/packs/application.jsでrequire('home/top’)とやって、rails serverを起動し直した。
②app/javascript/packにhome/application.jsを作り、そこで
require('home/top')と書いてapp/javascript/home/top.jsを読み込む。そしてapp/views/home/top.html.erbで
<% javascript_pack_tag 'home/application' %>とかいて読み込んだ。
→後々turbolinksを使っているため、②のやり方はできないということがわかったのでソースコードは①のやり方でやっています。

vscodeでhtmlとjsだけで確認したときはちゃんと作動したのでjsの書き方などに問題があるわけではないかと思います。top.jsでconsole.logで確かめたところエラーのようにconsoleに表示されなかったため、top.jsが読み込めていないんだと思います。ご協力お願いします。

1

2Answer

いや、できていなくて、
bodyの中でjsを読み込むとturbolinksはheadの中で読み込んでくださいというエラーが出るので
top.jsの一番下のところを
document.addEventListener('DOMContentLoaded', () => {
new PhotoViewer(document.getElementById('top'),images).init();
});
としたら画像を表示することができました。
DOMを構築する前に要素が取得されてされることが原因だったみたいです。

0Like

Your answer might help someone💌