質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.79%

Bootstrap 4のモーダルが正常に動かない

受付中

回答 0

投稿

  • 評価
  • クリップ 1
  • VIEW 384

vankick

score 22

現在、APIで情報を取得し、取得したアイテムをクリックすると、モーダルウインドウでアイテム詳細が見れるようになるよう実装をしようとしています。
data-targetには、APIで送られてくるidを設定しています。

アイテムをクリックすると、htmlに新たに追加されるのですが、画面上には現れることはなく、クローズも出来ないので、別にアイテムをクリックするとどんどんhtmlに追加されていってしまいます。

modalクラスに"-open"が追加されないがために起こっている問題かとは思うのですが、なかなか解決できません。どなたかお力をお貸しいただけないでしょうか。

index.js

import "./../styles/style.scss";
import { elements } from './views/base';
import Search from './models/Search';
import * as searchView from './views/searchView';
import Movie from './models/Movie';
import * as movieView from './views/movieView';
import { key, proxy } from './config';

const state = { };

window.onload = async function(){
    const query = "toy";

        state.search = new Search(query);
        console.log("New Search", state);

        try {
            await state.search.getResults();
            searchView.clearInput();
            searchView.renderResults(state.search.result);
        } catch (err) {
            console.log(err);
        }
}

const controlSearch = async () => {
    const query = searchView.getInput();

    if(query) {
        state.search = new Search(query);
        console.log("New Search", state);

        try {
            searchView.clearDefaultMovies();
            await state.search.getResults();
            searchView.clearInput();
            searchView.renderResults(state.search.result);
        } catch (err) {
            console.log(err);
        }
    }
}

elements.searchForm.addEventListener('submit', e => {
    event.preventDefault();
    controlSearch();
});

const controlMovie = async () => {
    const id = window.location.hash.replace('#', '');
    console.log("Hash", id);

    if(id) {

        state.movie = new Movie(id);

        try {
            movieView.clearMovie();
            await state.movie.getMovie();
            movieView.renderMovie(state.movie);

        } catch (err) {
            console.log(err);
        }
    }
}
window.addEventListener('hashchange', controlMovie);
一覧生成用

import { elements } from './base';

export const getInput = () => elements.searchInput.value;

export const clearDefaultMovies = () => {
    elements.searchRes.innerHTML = "";
}

export const clearInput = () => {
    elements.searchInput.value = '';
};

const renderMovie = result => {
    const markup = 
    `
        <li data-toggle="modal" data-target="#${result.id}" data-dismiss="modal">
            <a class="movie_item" href="#${result.id}">
                <div class="movie_image">
                    <div>
                        <img src="https://image.tmdb.org/t/p/original/${result.backdrop_path}" onerror="this.onerror=null;this.src='https://cdn.hands.net/images/4571253480919-1.jpg';" >              
                    </div>
                </div>
                <div class="movie_description">
                <p>#${result.id}</p>
                    <p class="movie_description_title">${result.original_title}</p>
                    <p class="movie_description_date">${result.release_date}</p>
                </div>
            </a>
        </li>
    `;
    elements.searchRes.insertAdjacentHTML('beforeend', markup);
    console.log("searchView", markup);
};

export const renderResults = (movies) => {

    movies.forEach(renderMovie);

};
詳細生成用

import { elements } from './base';

export const clearMovie = () => {
    elements.test.innerHTML = "";
}

export const renderMovie = movie => {
    const markup = 
    `
    <div class="modal fade" id="${movie.id}" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="demoModalTitle">タイトル</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">

<div class="detail_image">
                    <div>
                    <img src="https://image.tmdb.org/t/p/w500/${movie.image}" alt={movie.title} onerror="this.onerror=null;this.src='https://cdn.hands.net/images/4571253480919-1.jpg';" />
                    </div>
                </div>
                <div class="detail_description">
                    <p class="detail_description_title">${movie.title}</p>
                    <p class="detail_description_date">${movie.date}</p>
                    <p class="detail_description_txt">${movie.description}</p>
                </div>              
            </div>            
        </div>
    </div>
</div>       
    `;
    elements.searchForm.insertAdjacentHTML('afterend', markup);
    console.log("movieView", markup);
}
index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <title>Movie Search App in JavaScript</title>
  </head>

  <body>
    <div class="container">

      <form class="search">
        <a href="https://www.themoviedb.org/" target="_blank"><img height="60" src="https://www.themoviedb.org/assets/2/v4/logos/408x161-powered-by-rectangle-green-bb4301c10ddc749b4e79463811a68afebeae66ef43d17bcfd8ff0e60ded7ce99.png" /></a>
        <input type="text" class="search__field" />
        <button class="search__btn">Search</button>
      </form>

<!-- ここにモーダル要素が追加される -->

      <ul class="results"></ul>

    </div>
    <script src="dist/bundle.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

  </body>
</html>
export const elements = {
    searchForm: document.querySelector('.search'),
    searchRes: document.querySelector('.results'),
    searchInput: document.querySelector('.search__field'),
    movie: document.querySelector('.movie_item'),
    test: document.querySelector('.test'),
    // Modal window
    popup: document.querySelector('#js-popup'),
    blackBg: document.querySelector('#js-black-bg'),
    closeBtn: document.querySelector('#js-close-btn'),
    showBtn: document.querySelector('#js-show-popup')
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る