如何在Bootstrap 5 模态中指定API objects?
How to specify API objects in Bootstrap 5 modal?
我搞不清楚这个问题,已经研究了很长时间了。基本上,我正在使用这个电影应用程序并且需要一个模态。到目前为止,我必须指出要单独展示每部电影,展示他们的海报、标题和分数。
现在,我的想法是按下标题,模式将弹出描述 ${overview}。好的,它有效,但是! Modal 只显示第一个 object 的描述,无论我按哪个电影的标题。
删除模态并添加 <div>${overview}</div>
后,它会正常工作,正确显示每部电影的描述,但一旦我将其放入模态 - 将不起作用。
我试着尝试点击那个按钮,用谷歌搜索但找不到解决方案。任何帮助或指导都会很棒,谢谢!
是的,您基本上遗漏了两件事:
- 模态内容的文本颜色
- 每个按钮和模式的唯一 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
});
我搞不清楚这个问题,已经研究了很长时间了。基本上,我正在使用这个电影应用程序并且需要一个模态。到目前为止,我必须指出要单独展示每部电影,展示他们的海报、标题和分数。
现在,我的想法是按下标题,模式将弹出描述 ${overview}。好的,它有效,但是! Modal 只显示第一个 object 的描述,无论我按哪个电影的标题。
删除模态并添加 <div>${overview}</div>
后,它会正常工作,正确显示每部电影的描述,但一旦我将其放入模态 - 将不起作用。
我试着尝试点击那个按钮,用谷歌搜索但找不到解决方案。任何帮助或指导都会很棒,谢谢!
是的,您基本上遗漏了两件事:
- 模态内容的文本颜色
- 每个按钮和模式的唯一 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
});