简体   繁体   English

如何在动态 javascript 表中显示行数计数?

[英]How do I display the row number count in a dynamic javascript table?

I'm looping over an array on the front end using ejs and displaying the data in a bootstrap 5 table.我在前端使用 ejs 遍历数组并在 bootstrap 5 表中显示数据。 The table is dynamic so rows will be added and deleted with time.该表是动态的,因此行将随时间添加和删除。

All the data is coming through without an error and the table is populating, however, I'd like to have the first column show the "count" for each row.所有数据都没有错误地通过并且表格正在填充,但是,我想让第一列显示每一行的“计数”。 Eg., "1, 2, 3, 4, 5, etc".例如,“1、2、3、4、5 等”。

I've tried using indexOf without any success and since the code already exists in a loop, creating another loop requires me to switch my ejs syntax and I lose the ability to count the length of the array.我已经尝试使用indexOf但没有成功,并且由于代码已经存在于循环中,创建另一个循环需要我切换我的 ejs 语法并且我失去了计算数组长度的能力。

Below is my client side code that yields value -1 down the entire # column for each row:下面是我的客户端代码,它在每一行的整个#列中产生值-1

 <div class="col-12 d-flex flex-row-reverse">
  <a href="" class="a1" onclick="exportTableToCSV(null, 'text.csv')">Export to csv</a>
 </div>
 <div class="table-responsive">
<table class="table table-hover">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Email</th>
      <th scope="col">Gender</th>
      <th scope="col">Age</th>
      <th scope="col">Clicked IG</th>
      <th scope="col">Date Added</th>
      <th scope="col">Remove</th>
    </tr>
  </thead>
  <tbody>
    <% for (let fan of artist.fans){%>
    <tr>
      <th scope="row"><%= artist.fans.indexOf(fan.id) %></th>
      <td><%= fan.email %></td>
      <td><%= fan.gender %></td>
      <td><%= fan.age %></td>
      <td><%= fan.subscribed %></td>
      <td><%= fan.dateAdded %></td>
      <td style="padding-left: 2rem;">
        <button onclick="removeRow()" ></button>
         </td>
      <td style="padding-left: 2rem;"><i class="bi bi-trash"></i></td>
      <% } %> 
    </tr>
  </tbody>
</table>
</div>

If I switch artist.fans.indexOf(fan.id) with just fan.id I get the corresponding objectId for each fan email object.如果我将artist.fans.indexOf(fan.id) fan.id 我会得到每个粉丝对应的 objectId email object。

If I switch artist.fans.indexOf(fan.id) with artist.fans.length I get 7 down the # column for each row.如果我将artist.fans.indexOf(fan.id)artist.fans.length切换,我会在每一行的#列下得到7

Here's my db model:这是我的数据库 model:

const artistSchema = new Schema({
image: [ImageSchema], 
genre: [ String ], 
fans: [{ 
    email: String, 
    subscribed: String, 
    gender: String, 
    age: Number 
        dateAdded: {
            type: Date,
            default: Date.now
                }
      }], 
 });

How do I get each row to be numbered?如何让每一行编号?

the problem is that you used fan.id as a search param in artist.fans.indexOf(fan.id) which is not directly accessible throw the artist.fans so instead you need to use another method that accepts comparing function so you can compare their id问题是你在artist.fans.indexOf(fan.id)中使用了fan.id作为搜索参数,它不能直接访问抛出artist.fans所以你需要使用另一种方法来接受comparing function这样你就可以比较他们的身份证

try to use尝试使用

<th scope="row"><%= artist.fans.findIndex(f=> f.id == fan.id) %></th>

TL;DR:长话短说:

Just do this:只需这样做:

<% for( const fan of artist.fans.map( ( e, index ) => ({ index, ...e }) ) ) { %>
<tr>
    <th scope="row"><%= fan.index %></th>
    <td><%= fan.email %></td>
    <!-- etc -->
</tr>

<% }%>

Explanation:解释:

I'd like to have the first column show the "count" for each row.我想让第一列显示每一行的“计数”。 Eg., "1, 2, 3, 4, 5, etc".例如,“1、2、3、4、5 等”。

  • That's not a "count".这不是“计数”。 I would refer to that as "the row-number" (if 1-based) or "row-index" (if 0-based).我将其称为“行号”(如果基于 1)或“行索引”(如果基于 0)。

  • If you're using SQL to get your data then you can just use ROW_NUMBER() in your query and map it to some new number property in your Fan type.如果您使用 SQL 来获取数据,那么您只需在查询中使用ROW_NUMBER()并将其 map 用于Fan类型中的一些新number属性。

    • Note that a ROW_NUMBER() value is kinda meaningless without a well-defined ORDER BY criteria.请注意,如果没有明确定义的ORDER BY标准, ROW_NUMBER()值有点毫无意义。
  • Don't use indexOf in a loop : indexOf has a runtime complexity of O(n) so it's inadvisable to use that function inside a loop over the same array as that will give you O(n^2) runtime, which is very bad . 不要在循环中使用indexOfindexOf的运行时复杂度为O(n) ,因此不建议在同一数组的循环中使用 function,因为这会给你O(n^2)运行时,这是非常糟糕的.

    • This also applies to other O(n) reduction functions like findIndex , find , includes , and lastIndexOf .这也适用于其他O(n)缩减函数,如findIndexfindincludeslastIndexOf
    • Also, indexOf (and others) only defined on Array.prototype , so it isn't available on other kinds of iterables, such as NodeList .此外, indexOf (和其他)仅在Array.prototype上定义,因此它不适用于其他类型的可迭代对象,例如NodeList
  • Within ejs, you can use an overload of Array.prototype.map which gives you the index of each element , and stick the index into each element object, like so:在 ejs 中, 您可以使用Array.prototype.map的重载,它为您提供每个elementindex ,并将index粘贴到每个element object 中,如下所示:

const fansWithIndex = artist.fans
    .map( function( element, index ) {
        element.index = index;
        return element;
    } );

<% for( const fan of fansWithIndex ) { %>
<tr>
    <th scope="row"><%= fan.index %></th>
    <td><%= fan.email %></td>
    <!-- etc -->
</tr>

<% }%>

...though FP purists (like myself) would argue that the above example is bad code because it mutates source data, and instead Object.assign should be used instead. ...虽然 FP 纯粹主义者(像我自己)会争辩说上面的例子是错误的代码,因为它改变了源数据,而应该使用Object.assign代替。 Also, the long-form function can be made simpler with an arrow-function => , like this:此外,长格式function可以使用箭头函数=>变得更简单,如下所示:

const fansWithIndex = artist.fans.map( ( e, idx ) => Object.assign( { index: idx }, e ) );

<% for( const fan of fansWithIndex ) { %>
<tr>
    <th scope="row"><%= fan.index %></th>
    <td><%= fan.email %></td>
    <!-- etc -->
</tr>

<% }%>

This can be simplified further:这可以进一步简化:

const fansWithIndex = artist.fans.map( ( e, index ) => ({ index, ...e }) );

<% for( const fan of fansWithIndex ) { %>
<tr>
    <th scope="row"><%= fan.index %></th>
    <td><%= fan.email %></td>
    <!-- etc -->
</tr>

<% }%>
  • Because the artist.fans.map(...) part is a single expression with a single output you can now inline it directly into your for(of) statement, like so:因为artist.fans.map(...)部分是带有单个 output 的单个表达式,您现在可以将其直接内联到您的for(of)语句中,如下所示:
<% for( const fan of artist.fans.map( ( e, index ) => ({ index, ...e }) ) ) { %>
<tr>
    <th scope="row"><%= fan.index %></th>
    <td><%= fan.email %></td>
    <!-- etc -->
</tr>

<% }%>

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

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