简体   繁体   English

从javascript数组生成动态html卡

[英]Generating dynamic html cards from a javascript array

I would like to display some card elements in HTML. 我想在HTML中显示一些卡片元素。 I would like to get the variables of the card element from a javascript array.(Such as title etc..). 我想从javascript数组中获取card元素的变量。(例如title等。)。 The card element number will also depend on the Javascript array size. 卡元素号还将取决于Javascript数组的大小。 I have looked at other questions such as generating dynamic tables but as I have a long customized html code block, it doesn't work. 我看过其他问题,例如生成动态表,但是由于我有一个很长的自定义html代码块,所以它不起作用。

This is for a website that I am building. 这是我正在建立的网站。 I already got the variables from an api end point with a HTTP get request but am unable to display as I wish to. 我已经从带有HTTP get请求的api端点获取了变量,但是无法如我所愿地显示。 I have looked at many similar questions but can't find the answer that I am looking for. 我看过许多类似的问题,但找不到所需的答案。

This is the script for getting the variables with the HTTP get request 这是用于通过HTTP get请求获取变量的脚本

<script>
const request = new XMLHttpRequest();

request.open('GET', 'api/seminars', true);
request.onload = function() {
  // Begin accessing JSON data here
  const data = JSON.parse(this.response);

  if (request.status >= 200 && request.status < 400) {
    data.forEach(resultArray => {
      document.getElementById('output').innerHTML = resultArray.name;
      document.getElementById('description').innerHTML =
        resultArray.description;
      document.getElementById('date').innerHTML = resultArray.date;
    });
  } else {
    console.log('error');
  }
};

request.send();
</script>

HTML CODE : HTML代码:

<div id="accordion">
    <div class="card">
        <div class="card-header" id="headingOne">
            <h5 class="mb-0">
                <button class="btn btn-link" data-toggle="collapse" data- target="#collapseOne" aria-expanded="true"
                    aria-controls="collapseOne">

                </button>
            </h5>
        </div>

        <div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordion">
            <div class="card-body">

                <h5 id="name"></h5>
                <p id="description"></p>
                <p id="description"></p>
                ...
            </div>
        </div>
    </div>
</div>

And I have continued html code from here on not relevant .. 而且我从这里继续不相关的html代码。

If there are 3 objects in my array, I would like to create 3 different cards and display name,description.. attributes. 如果我的数组中有3个对象,我想创建3个不同的卡,并显示名称,description ..属性。 But my code only creates one card and displays last object's attributes. 但是我的代码仅创建一张卡并显示最后一个对象的属性。

You code never really "creates" elements based on your API call - It just updates (ie, overwrites) the existing dom elements by updating the innerHTML of fixed elements referenced by their IDs. 您的代码永远不会真正根据您的API调用“创建”元素-它只是通过更新由其ID引用的固定元素的innerHTML来更新(即覆盖)现有dom元素。

If my interpretation of your code is correct, you should be only seeing the LAST item in your API result. 如果我对您的代码的解释正确,那么您应该只会在API结果中看到LAST项目。 There are also some other weird stuff going on like duplicate IDs which Im guessing are typos 还有其他一些奇怪的事情,例如重复的ID,我猜是错别字

To fix this, create a new div.card-body for each item your API returns and append it to your container 要解决此问题,请为API返回的每个项目创建一个新的div.card-body并将其附加到您的容器中

 const apiResult = [{ title: "title1", description: "desc1", output: "out1" }, { title: "title2", description: "desc2", output: "out2" }, { title: "title3", description: "desc3", output: "out3" }]; const container = document.getElementById('accordion'); apiResult.forEach((result, idx) => { // Create card element const card = document.createElement('div'); card.classList = 'card-body'; // Construct card content const content = ` <div class="card"> <div class="card-header" id="heading-${idx}"> <h5 class="mb-0"> <button class="btn btn-link" data-toggle="collapse" data-target="#collapse-${idx}" aria-expanded="true" aria-controls="collapse-${idx}"> </button> </h5> </div> <div id="collapse-${idx}" class="collapse show" aria-labelledby="heading-${idx}" data-parent="#accordion"> <div class="card-body"> <h5>${result.title}</h5> <p>${result.description}</p> <p>${result.output}</p> ... </div> </div> </div> `; // Append newyly created card element to the container container.innerHTML += content; }) 
 .card { padding: 1rem; border: 1px solid black; margin: 1rem; } 
 <div id="accordion"> </div> 

Note: 注意:

While this works, it's not very scalable. 尽管这可行,但伸缩性不是很好。 There are some great templating libraries out there with much more advanced interpolation features that you can consider if you have to do something like this in many places (and maintain it) 那里有一些很棒的模板库,它们具有更高级的插值功能,如果您必须在许多地方做这样的事情(并进行维护),可以考虑一下

jsRender jsRender

Underscore Templates 下划线模板

Handlebars 把手

UI frameworks like Vue , React , Angular wrap templating with binding to data models and handle auto updating the DOM for you to make things like this easier. 诸如VueReact ,Angular wrap模板之类的UI框架具有绑定到数据模型的功能,并为您处理自动更新DOM的工作,从而简化了此类工作。 Worth investigating if you have a lot of dynamically updating parts on your webpage 值得调查的是,如果您的网页上有很多动态更新的部分

You are overwriting the description's innerHTML with every repetition of your for loop . 您每次for loop重复都将覆盖描述的innerHTML。

Change this 改变这个

 document.getElementById('output').innerHTML = resultArray.name; document.getElementById('description').innerHTML = resultArray.description; document.getElementById('date').innerHTML = resultArray.date; 

to this 对此

 var element = document.createElement('div'); // create new div var name = document.createElement('h4'); name.innerHTML = resultArray.name; element.appendChild(name); var description = document.createElement('p'); description.innerHTML = resultArray.description; element.appendChild(description); var date = document.createElement('span'); date.innerHTML = resultArray.date; element.appendChild(date); document.body.appendChild(element); 

Suppose you have already queried the API, a way of doing it could be: 假设您已经查询了API,一种实现方法可能是:

 // Supposing you already have queried the API and have your data let data = [ {name: 'name0', description: 'description', date: 'XX/XX/XXXX'}, {name: 'name1', description: 'description', date: 'XX/XX/XXXX'}, {name: 'name2', description: 'description', date: 'XX/XX/XXXX'}, ] data.forEach(res => { let card = document.createElement("div"); let name = document.createTextNode('Name:' + res.name + ', '); card.appendChild(name); let description = document.createTextNode('Description:' + res.description + ', '); card.appendChild(description); let date = document.createTextNode('date:' + res.date); card.appendChild(date); let container = document.querySelector("#container"); container.appendChild(card); }); 
 <!-- At one point where you want to generate the cards you put this container --> <div id="container"></div> 

Yours was not working since you updated always the same elements instead of appending new ones :) 您的列表无法正常运行,因为您总是更新相同的元素,而不是添加新的元素:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM