如何在Bootstrap 5 模态中指定API objects?

How to specify API objects in Bootstrap 5 modal?

我搞不清楚这个问题,已经研究了很长时间了。基本上,我正在使用这个电影应用程序并且需要一个模态。到目前为止,我必须指出要单独展示每部电影,展示他们的海报、标题和分数。

现在,我的想法是按下标题,模式将弹出描述 ${overview}。好的,它有效,但是! Modal 只显示第一个 object 的描述,无论我按哪个电影的标题。

删除模态并添加 <div>${overview}</div> 后,它会正常工作,正确显示每部电影的描述,但一旦我将其放入模态 - 将不起作用。

我试着尝试点击那个按钮,用谷歌搜索但找不到解决方案。任何帮助或指导都会很棒,谢谢!

请在此处查看代码:https://github.com/sscip/movie-app-ms2

是的,您基本上遗漏了两件事:

  1. 模态内容的文本颜色
  2. 每个按钮和模式的唯一 ID

这是一个可行的解决方案: P.S:您也可以在 JSfiddle here.

上查看

// API link with key, please follow readme how to create own API key for application to work.

const APIKey = 'dontreallyneedit';
const APIURL = "https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=" + APIKey + "&page-1";
const IMGPath = "https://image.tmdb.org/t/p/w1280";
const SearchAPI = "https://api.themoviedb.org/3/search/movie?&api_key=" + APIKey + "&query=";

const mainSection = document.getElementById("main-section"); // selecting DOM element to work with
const searchForm = document.getElementById("search-form");
const searchInput = document.getElementById("search-field");


movies(APIURL); // calling popular movies funcion to work 

async function movies(url) {
  /* const resp = await fetch(url);
  const respData = await resp.json(); */

  const results = [{
      poster_path: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTP4mb3V7kJHqWTf5GUr-wHUOfHaTv71Ypf3-WGYqjJr-OpYPJslwk2IYY-Phi4hGxpfFQ&usqp=CAU",
      title: "Movie 1",
      vote_average: 5,
      overview: "Great Overview One!"
    },
    {
      poster_path: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTP4mb3V7kJHqWTf5GUr-wHUOfHaTv71Ypf3-WGYqjJr-OpYPJslwk2IYY-Phi4hGxpfFQ&usqp=CAU",
      title: "Movie 2",
      vote_average: 4,
      overview: "Great Overview Two!"
    },
    {
      poster_path: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTP4mb3V7kJHqWTf5GUr-wHUOfHaTv71Ypf3-WGYqjJr-OpYPJslwk2IYY-Phi4hGxpfFQ&usqp=CAU",
      title: "Movie 3",
      vote_average: 3,
      overview: "Great Overview Three!"
    }

  ];

  showMovies(results);
}

function showMovies(movies) {


  mainSection.innerHTML = ""; // clearing page to show new reults

  movies.forEach((movie, index) => {
    const {
      poster_path,
      title,
      vote_average,
      overview
    } = movie; // Pulling necessary names from API

    const movieBox = document.createElement("div"); //creating a div for individual movie elements
    movieBox.classList.add("movie"); // creating a class for it

    movieBox.innerHTML = `
      <div class="movie-image"><img src="${poster_path}" alt="${title}" /></div>
      <div class="movie-info">
        <button type="button" class="btn" data-bs-toggle="modal" data-bs-target="#exampleModal_${index}">
          ${title}
        </button>
        <span class="${classByRating(vote_average)}">${vote_average}</span>
        
        <div class="modal fade" id="exampleModal_${index}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
          <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
            <div class="modal-content">
              <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">${title}</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
              </div>
              <div class="modal-body">
                ${overview}
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    `; // creating markup for every movie element and pulling information from API
    mainSection.appendChild(movieBox); // sending back to HTML file
  });
}


function classByRating(vote) { //checking how high is the movie rating and giving apropriate class name.
  if (vote >= 8) {
    return "green";
  } else if (vote >= 5) {
    return "amber"
  } else {
    return "red";
  }
}


searchForm.addEventListener("submit", (i) => {
  i.preventDefault();

  const searchTerm = searchInput.value;

  if (searchTerm) {
    movies(SearchAPI + searchTerm)
    searchInput.value = "";
  }
})
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@100;300&display=swap');
.modal-content {
  color: black;
}


/* Main Styles */

* {
  box-sizing: border-box;
  font-family: 'Lato', serif;
}


/* Navigation */

header {
  background-color: #D16BA5;
  padding: 1rem 0.5rem;
}

header a {
  font-size: 1.5rem;
}

header button:focus {
  outline: none;
}

#navbar-brand {
  font-size: 1.7rem;
}

#search-field {
  border-radius: 10px;
  font-size: 1.2rem;
  border: none;
}

.search-btn:focus {
  outline: none;
}

.search-btn:active {
  background-color: #FF8F80;
}

.search-btn {
  font-size: 1.2rem;
  padding: 0 1rem;
  border: none;
  border-radius: 10px;
  color: #eee;
  background-color: #FF8F80;
}


/* Main section styling */

#main-section {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}


/* Movies Box styling */

.movie {
  margin: 0.7rem;
  width: 15rem;
  border-radius: 5px;
  background-color: #FF8F80;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  overflow: hidden;
}


/* Movie image */

.movie img {
  max-width: 100%;
}


/* Movie Basic info */

.movie-info {
  display: flex;
  justify-content: space-between;
  color: #eee;
  padding: 0.5rem;
  align-items: center;
  max-height: 100%;
}

.movie-info h3 {
  margin: 0;
  font-size: 1.21rem;
}

.movie-info span {
  background-color: #D16BA5;
  padding: 0.5rem;
  border-radius: 5px;
  width: 2.5rem;
  height: 2.5rem;
  text-align: center;
  font-weight: bold;
}

.movie-info span.green {
  color: rgb(0, 214, 54);
}

.movie-info span.amber {
  color: rgb(255, 163, 87);
}

.movie-info span.red {
  color: rgb(223, 45, 0);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- Title -->
  <title>Movies TOP-20 LIVE!</title>
  <!-- Bootstrap 5 CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <!-- Font Awesome 5 -->
  <script src="https://kit.fontawesome.com/0d4c39c5bf.js" crossorigin="anonymous"></script>
  <!-- Custom CSS -->
  <link rel="stylesheet" href="assets/css/styles.css" />
  <!-- Custom JS -->
  <script src="assets/js/config.js" type="text/javascript" defer></script>
  <script src="assets/js/script.js" type="text/javascript" defer></script>
</head>

<body>
  <header>
    <nav class="navbar navbar-expand-lg navbar-dark">
      <div class="container-fluid">
        <a class="navbar-brand" id="navbar-brand" href="#">Movies TOP-20 LIVE</a>
        <button class="navbar-toggler" id="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Contact Us</a>
            </li>
          </ul>
          <form class="d-flex" id="search-form">
            <input class="form-control me-2" id="search-field" type="search" placeholder="Search" aria-label="Search">
            <button class="search-btn" id="search-btn" type="submit">
              Search
            </button>
          </form>
        </div>
      </div>
    </nav>
  </header>
  <section id="main-section"></section>

  <!-- Bootstrap 5 JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>

</html>

您需要更改 data-bs-target 以绑定不同的按钮和模式。

  movies.forEach((movie) => {
    const {poster_path, title, vote_average, overview, uid} = movie; // Pulling necessary names from API
    console.log(overview)

    const movieBox = document.createElement("div"); //creating a div for individual movie elements
    movieBox.classList.add("movie"); // creating a class for it

    movieBox.innerHTML = `
      <div class="movie-image"><img src="${IMGPath + poster_path}" alt="${title}" /></div>
      <div class="movie-info">
        <button type="button" class="btn" data-bs-toggle="modal" data-bs-target="#${uid}">
          ${title}
        </button>
        <span class="${classByRating(vote_average)}">${vote_average}</span>
        
        <div class="modal fade" id="${uid}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
          <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
            <div class="modal-content">
              <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">${title}</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
              </div>
              <div class="modal-body">
                ${overview}
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    `; // creating markup for every movie element and pulling information from API

    

    mainSection.appendChild(movieBox); // sending back to HTML file
  });

varying-modal-content