提问人:Victoria 提问时间:9/27/2023 更新时间:10/10/2023 访问量:30
使用 AJAX 请求更新 ejs 模板
Updating ejs template with AJAX request
问:
我正在创建一个 Web 应用程序,当用户搜索特定成分时,该应用程序会返回食谱。我正在使用 edamam api 并决定使用分页,这样当用户单击“加载更多”按钮时,我就可以加载相对于用户搜索的更多食谱。请注意,edamam 一次将返回 20 个食谱。 这是来自 edaam 关于其分页工作原理的文档:
与版本 1 相比,配方搜索 API 中的分页工作方式发生了重大变化。不再支持 from 和 to 的参数。相反,响应将包含 _links.next.href 中下一个请求的预构造 URL。如果此路径不存在,则这是最后一页,没有更多结果。
我在很大程度上使此功能起作用,但是,我的html中有一部分使用了ejs if语句,该语句导致了一些问题(“loadrecipes.js”中的问题)。
我的问题是 2 个:
- 如何解决 if 语句的问题?
- 在使用 AJAX 请求时,有没有更好的方法来更新 ejs?
代码。Git hub repo 在此处以便于查看
我有 3 个文件:
- index.js - 服务器端代码
- index.ejs - 带有 EJS 模板的 HTML
- loadrecipes.js - 客户端代码
索引.js
import express from "express";
import axios from "axios";
import bodyParser from "body-parser";
import 'dotenv/config';
const app = express();
const port = 3000;
const API_URL = "https://api.edamam.com/api/recipes/v2?type=public";
const myId = process.env.ID;
const myAPIKey = process.env.API_KEY;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
let nextPageUrl = null;
app.get("/", (req, res) => {
res.render("index.ejs");
})
app.post("/search", async (req, res) => {
const inputText = req.body.ingrediants;
try{
const requestUrl = nextPageUrl || API_URL;
const response = await axios.get(requestUrl, {
params: {
q: inputText,
app_id: myId,
app_key: myAPIKey
}
});
const result = response.data;
//store next page url for pagination
if(result._links.next.href){
nextPageUrl = result._links.next.href;
} else{
nextPageUrl = null; //no more pages/recipes given the user search
}
res.render("index.ejs", {
recipes: result,
userInput: inputText,
nextPageUrl: nextPageUrl
});
}catch(error){
res.render("index.ejs", {
content: "Looks like there's an issue: " + error.message
});
}
})
app.listen(port, () => {
console.log(`Server listening on port ${port}.`);
})
索引.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cook Your Kitchen</title>
<link rel="stylesheet" type="text/css" href="styles/main.css">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="px-4 py-5 my-4 text-center">
<h1 class="display-5 fw-bold text-body-emphasis">Cook Your Kitchen</h1>
<div class="col-lg-6 mx-auto">
<p class="lead mb-4">Have some random ingrediants in your kitchen? <br>
Those veggies about to go bad?? <br>
Enter the ingrediants you want to use and get recipe suggestions!
</p>
<form action="/search" method="post">
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<input type="text" id="search" name="ingrediants" class="form-control"
placeholder="Chicken, beans, tomato,..." aria-label="Recipient's username"
aria-describedby="button-addon2">
<button class="btn btn-outline-secondary" type="submit" value="Submit" id="button-addon2">Get a recipe</button>
</div>
</form>
</div>
</div>
</div>
<% if(locals.recipes){ %>
<div class="container px-4 py-5" id="custom-cards">
<h2>You searched for: <%= userInput %>
</h2>
<div id="recipe-list" class="row row-cols-1 row-cols-lg-3 align-items-stretch g-4 py-5">
<% recipes.hits.forEach(recipe=> { %>
<div class="col" onclick="location.href='<%= recipe.recipe.url %>';">
<div class="card card-cover h-100 overflow-hidden text-bg-dark rounded-4"
style="background-image: url('<%= recipe.recipe.image %>');">
<div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1 text-bg">
<h3 class="mt-5 mb-4 display-6 lh-1 fw-bold">
<%= recipe.recipe.label %>
</h3>
<ul class="d-flex list-unstyled mt-auto">
<% if (recipe.recipe.dietLabels.length > 0) { %>
<li class="badge text-bg-dark rounded-pill px-2">
<small>
<%= recipe.recipe.dietLabels[0]%>
</small>
</li>
<%} %>
<li class="badge text-bg-dark rounded-pill mx-2 px-2">
<small>
<%= recipe.recipe.healthLabels[0] %>
</small>
</li>
<li class="badge text-bg-dark rounded-pill px-2">
<small>
<%= recipe.recipe.healthLabels[1] %>
</small>
</li>
</ul>
</div>
</div>
</div>
<% })} %>
</div>
</div>
<% if (locals.nextPageUrl){ %>
<div class="text-center mb-4">
<button type="button" class="btn btn-light" id="loadMoreButton" data-next-page="<%= nextPageUrl %>">Load More</button>
</div>
<% } %>
<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4="
crossorigin="anonymous"></script>
<script src="loadrecipes.js"></script>
</body>
</html>
这是我尝试更新的index.ejs中的部分(红框),在此处输入图像描述
加载食谱.js
const nextPageUrl = $("#loadMoreButton").data("next-page");
$("#loadMoreButton").on("click", (event) => {
event.preventDefault();
event.stopPropagation();
//using ajax to load more recipes
if (nextPageUrl) {
$.ajax({
method: "GET",
url: nextPageUrl,
success: (result) => {
// Append result to the existing recipes
// and update the nextPageUrl data attribute if there's a next page.
const moreRecipes = result.hits;
if(moreRecipes.length > 0){
moreRecipes.forEach((recipe) => {
//copying card html/ejs from index.ejs and replacing ejs tags for each additionally retrieved recipe
const recipeCard = `
<div class="col" onclick="location.href='${recipe.recipe.url}';">
<div class="card card-cover h-100 overflow-hidden text-bg-dark rounded-4"
style="background-image: url('${recipe.recipe.image}');">
<div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1 text-bg">
<h3 class="mt-5 mb-4 display-6 lh-1 fw-bold">
${recipe.recipe.label}
</h3>
<ul class="d-flex list-unstyled mt-auto">
<% if (${recipe.recipe.dietLabels.length} > 0) { %>
<li class="badge text-bg-dark rounded-pill px-2">
<small>
${recipe.recipe.dietLabels[0]}
</small>
</li>
<%} %>
<li class="badge text-bg-dark rounded-pill mx-2 px-2">
<small>
${recipe.recipe.healthLabels[0]}
</small>
</li>
<li class="badge text-bg-dark rounded-pill px-2">
<small>
${recipe.recipe.healthLabels[0]}
</small>
</li>
</ul>
</div>
</div>
</div>
`;
// Append the new recipe card to the recipe list div
$("#recipe-list").append(recipeCard);
});
// Update the nextPageUrl data attribute
$("#loadMoreButton").data("next-page", result._links.next.href);
} else {
// If there are no more recipes, hide the "Load More" button
$("#loadMoreButton").hide();
}
}
});
}
})
我一直在查看堆栈溢出上发布的文档和其他类似问题,但没有发现太多对这个确切问题有帮助的东西。任何帮助将不胜感激!
答:
1赞
Victoria
10/10/2023
#1
经过大量的反复试验并阅读了各种文档,我通过创建一个全局变量来解决我的问题,该变量包含需要更新+附加的饮食标签html/ejs。我在loadrecipes.js的recipeCard变量中拉出if语句。并将 if 语句的参数分配给饮食标签变量。然后,我在食谱卡更新中引用了饮食标签变量。我相信有一个更好的解决方案,但这就是我提出的有效方法。
const nextPageUrl = $("#loadMoreButton").data("next-page");
$("#loadMoreButton").on("click", (event) => {
event.preventDefault();
event.stopPropagation();
let dietLabel = "";
//using ajax to load more recipes
if (nextPageUrl) {
$.ajax({
method: "GET",
url: nextPageUrl,
success: (result) => {
// Append result to the existing recipes
// and update the nextPageUrl data attribute if there's a next page.
const moreRecipes = result.hits;
if(moreRecipes.length > 0){
moreRecipes.forEach((recipe) => {
if(recipe.recipe.dietLabels.length > 0){
dietLabel = `
<li class="badge text-bg-dark rounded-pill px-2">
<small>
${recipe.recipe.dietLabels[0]}
</small>
</li>
`;
}
//copying card html/ejs from index.ejs and replacing ejs tags for each additionally retrieved recipe
const recipeCard = `
<div class="col" onclick="location.href='${recipe.recipe.url}';">
<div class="card card-cover h-100 overflow-hidden text-bg-dark rounded-4"
style="background-image: url('${recipe.recipe.image}');">
<div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1 text-bg">
<h3 class="mt-5 mb-4 display-6 lh-1 fw-bold">
${recipe.recipe.label}
</h3>
<ul class="d-flex list-unstyled mt-auto">
${dietLabel}
<li class="badge text-bg-dark rounded-pill mx-2 px-2">
<small>
${recipe.recipe.healthLabels[0]}
</small>
</li>
<li class="badge text-bg-dark rounded-pill px-2">
<small>
${recipe.recipe.healthLabels[1]}
</small>
</li>
</ul>
</div>
</div>
</div>
`;
// Append the new recipe card to the recipe list div
$("#recipe-list").append(recipeCard);
});
// Update the nextPageUrl data attribute
$("#loadMoreButton").data("next-page", result._links.next.href);
} else {
// If there are no more recipes, hide the "Load More" button
$("#loadMoreButton").hide();
}
}
});
}
})
评论