NodeJS 使用AJAX请求更新ejs模板

pdtvr36n  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(135)

我正在创建一个Web应用程序,当用户搜索特定成分时,它会返回食谱。我正在使用edamam API,并决定使用分页,这样当用户点击“加载更多”按钮时,我就可以加载相对于用户搜索的更多食谱。请注意,edamam一次会返回20个食谱。这是来自edamam关于分页工作原理的文档:
配方搜索API中分页的工作方式与版本1相比发生了重大变化。不再支持from和to参数。相反,响应将在_links. next. href中包含下一个请求的预构造URL。如果此路径不存在,则这是最后一页,并且没有更多结果。
我在很大程度上实现了这个功能,但是,我的html中有一部分使用了ejs if语句,这导致了一些问题(“loadrecipes.js”中的问题)。
我的问题有两个方面:
1.如何解决if语句的问题?
1.在使用AJAX请求时,有没有更好的方法来更新ejs?

代码. Git hub repo is here,方便查看

我有三个文件:

  1. index.js -服务器端代码
    1.使用ejs模板的html
  2. loadrecipes.js -客户端代码

index.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}.`);
})

index.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中的部分(红色框)enter image description here

loadrecipes.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();
                    }
                }
        });
    }
})

我一直在浏览有关堆栈溢出的文档和其他类似的问题,但没有找到对这个问题有帮助的东西。任何帮助将不胜感激!

p4tfgftt

p4tfgftt1#

经过大量的试验和错误和阅读各种文档,我解决了我的问题,创建一个全局变量来保存需要更新+追加的饮食标签html/ejs。我在loadrecipes.js的recipeCard变量中取出if语句。并将if语句的参数赋给diet标签变量。然后,我在食谱卡更新中引用了饮食标签变量。我相信有一个更好的解决方案,但这是我想出的工作。

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();
                    }
                }
        });
    }
})

相关问题