【问题标题】:Data loading issue in Table using D3 version 4使用 D3 版本 4 的表中的数据加载问题
【发布时间】:2020-05-06 19:48:50
【问题描述】:

我有一个表格,当我单击一个按钮时,该表格将填充数据。以下是片段:

function myFunction() {
	myTable = d3.select("#mytable");
	myTable.selectAll("td").remove();
	var rows = add_temp_rows(myTable);
}

function add_temp_rows(table) {
 	data = [{"a" : get_rand_temp(),
           "b" : get_rand_temp()
          }, 
          {"a" : get_rand_temp(),
           "b" : get_rand_temp()
          },
          {"a" : get_rand_temp(),
           "b" : get_rand_temp()
          }];
	var rows = table
		.select('tbody')
		.selectAll('tr')
		.data(data);
		
	rows.enter()
		.append("tr")
		.merge(rows);

	rows.exit().remove();
  
  rows.selectAll("td")
      .data(function (d) {
        return [d.a, d.b];
      })
      .enter()
      .append('td')
      .text(function (d) {
        return d;
      });
  return rows;
}

function get_rand_temp() {
	var precision = 100;
	return Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision);
}
<!DOCTYPE html>

<head>
    <title>Test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>

<body>

    <div class="container">
      
        <div class="row">
            <button onclick="myFunction()">Try it</button>
            <div id="FilterableTable2" class="col-8">
                <div class="table-responsive">
                    <table class="table table-striped table-dark" id="mytable">
                        <thead class='thead-dark'>
                            <tr>
                                <th>Col1</th>
                                <th>Col2</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>test</td>
                                <td>test2</td>
                            </tr>
                            <tr>
                                <td>test3</td>
                                <td>test4</td>
                            </tr>
                            <!--<tr>
                                <td>test</td>
                                <td>test2</td>
                            </tr>
                            <tr>
                                <td>test3</td>
                                <td>test4</td>
                            </tr>
                            -->
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>


    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"
        integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
  
    <!-- D3 -->
  
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <!-- <script src="https://d3js.org/d3.v5.min.js"></script> -->

    <script src="js/main.js"></script>
</body>

现在我有几个问题:

  1. 如果表格一开始是空的,第一次点击不会填充表格,但第二次点击以后会正确填充。虽然我在 Chrome 中检查并看到第一次点击仍然得到处理并打印了一些数据。
  2. 如果我在 HTML 中硬编码了一些初始值,并且硬编码的行数等于或大于新数据的数量,那么它会从第一次点击开始正常工作。
  3. 如果初始硬编码行较少(但不为空),第一次单击将更改这些行的数据,但不会添加更多行以匹配数据。但第二次点击会追加正确的行数。

我可以知道如何解决这个问题吗?我正在从 D3 v3 迁移到 v4,有许多重大变化。理想情况下,我想要的是,每次点击都会更改表格以显示正确的数据行。

【问题讨论】:

    标签: javascript jquery d3.js


    【解决方案1】:

    错误是在第一次调用期间,对象行不包含使用 .enter() 创建的新 tr,即使 .merge(row) 命令 d3js.org。所以 rows.selectAll("td") 不会影响新的 tr。在第二次调用期间选择新创建的 tr。

    所以要第一次调用就生效,解决方法是在.merge(row)之后调用.selectAll("td")。

        //...
        rows.enter()
            .append("tr")
            .merge(rows)
            .selectAll("td")
            .data(function (d) {
                return [d.a, d.b];
            })
            .enter()
            .append('td')
            .text(function (d) {
                return d;
            });
        //...
    

    <!DOCTYPE html>
    
    <head>
        <title>Test</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- bootstrap -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
            integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    </head>
    
    <body>
    
        <div class="container">
          
            <div class="row">
                <button onclick="myFunction()">Try it</button>
                <div id="FilterableTable2" class="col-8">
                    <div class="table-responsive">
                        <table class="table table-striped table-dark" id="mytable">
                            <thead class='thead-dark'>
                                <tr>
                                    <th>Col1</th>
                                    <th>Col2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>test</td>
                                    <td>test2</td>
                                </tr>
                                <tr>
                                    <td>test3</td>
                                    <td>test4</td>
                                </tr>
                                <!--<tr>
                                    <td>test</td>
                                    <td>test2</td>
                                </tr>
                                <tr>
                                    <td>test3</td>
                                    <td>test4</td>
                                </tr>
                                -->
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    
    
        <!-- jQuery -->
        <!-- script src="https://code.jquery.com/jquery-3.5.1.min.js"
            integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script -->
      
        <!-- D3 -->
      
        <!-- script src="https://d3js.org/d3.v4.min.js"></script -->
        <script src="https://d3js.org/d3.v5.min.js"></script>
    
        <!-- script src="js/main.js"></script -->
    
    <script>
    function myFunction() {
    	myTable = d3.select("#mytable");
    	myTable.selectAll("td").remove();
    	var rows = add_temp_rows(myTable);
    }
    
    function add_temp_rows(table) {
     	data = [{"a" : get_rand_temp(),
               "b" : get_rand_temp()
              }, 
              {"a" : get_rand_temp(),
               "b" : get_rand_temp()
              },
              {"a" : get_rand_temp(),
               "b" : get_rand_temp()
              }];
    	var rows = table
    		.select('tbody')
    		.selectAll('tr')
    		.data(data);
    		
    	rows.enter()
    		.append("tr")
    		.merge(rows)
        .selectAll("td")
          .data(function (d) {
            return [d.a, d.b];
          })
          .enter()
          .append('td')
          .text(function (d) {
            return d;
          });
    
    	rows.exit().remove();
      
      return rows;
    }
    
    function get_rand_temp() {
    	var precision = 100;
    	return Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision);
    }
    </script>
    </body>
    </html>

    【讨论】:

    • 谢谢。那么merge(rows) 不会就地修改rows 对象吗?相反,如果我分配 new_rows = rows.enter().append("tr").merge(rows),那么这个 new_rows 将包含所有内容,对吗?
    • 是的。 rows...merge(rows) 不修改对象行,但包含新闻行。
    猜你喜欢
    • 1970-01-01
    • 2016-11-21
    • 2019-04-09
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    相关资源
    最近更新 更多