【问题标题】:How to add row in datatable - DC.js如何在数据表中添加行 - DC.js
【发布时间】:2020-05-13 04:01:31
【问题描述】:

我有一个 json 文件,它根据当前年份和上一年为销售人员加载销售数据。

我创建了一个表格,其中显示了每个销售人员每年的总销售额,在最后一行,我需要加载所有销售人员的总销售额。如下图所示:

我正在使用dc.dataTable 创建我的表。

您能否告诉我 DC.js 中是否有任何方法可以在我的表中创建一行来放置总销售额?

这是我的代码,提前谢谢你。

var vendedorTable = dc.dataTable("#Vendedores");

var url = 'http://www.json-generator.com/api/json/get/cgsUhkPSjS?indent=2';
d3.json(url).then(function(data) {

  data.forEach(function(d) {

    var myCrossfilter = crossfilter(data);
    var all = myCrossfilter.groupAll();

    dc.dataCount(".dc-data-count")
      .dimension(myCrossfilter)
      .group(all);

    vendedorDim = myCrossfilter.dimension(function(d) {
      return d.vendnm;
    });

    var vendedorGroup = vendedorDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);

    function reduceAdd(p, v) {
      p.totalAno += +v.Vendas_Ano;
      p.totalHomologo += +v.Vendas_Ant;
      return p;
    }

    function reduceRemove(p, v) {
      p.totalAno -= v.Vendas_Ano;
      p.totalHomologo -= v.Vendas_Ant;
      return p;
    }

    function reduceInitial() {
      return {
        totalAno: 0,
        totalHomologo: 0,
      };
    }

    // formatter = d3.format(".3s");
    // formatter2 = d3.format(".0%");

    //Fake Dimension
    rank = function(p) {
      return ""
    };

    function checkRows(d) {
      if (d.value.totalAno <= 0 || isNaN(d.value.totalAno) || d.value.totalHomologo <= 0 || isNaN(d.value.totalHomologo)) {
        return 0;
      }
      return d;
    }

    //vendedorTable
    vendedorTable.width(500)
      .height(480)
      .dimension(vendedorGroup)
      .group(rank)
      .columns([function(d) {
          d = checkRows(d);
          while (d != 0) {
            return d.key;
          }
        },
        function(d) {
          d = checkRows(d);
          while (d != 0) {
            return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
              minimumFractionDigits: 2
            }) + '€';
          }
        },
        function(d) {
          d = checkRows(d);
          while (d != 0) {
            return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
              minimumFractionDigits: 2
            }) + '€';
          }
        }
      ])
      .sortBy(function(d) {
        return d.value.totalAno
      })
      .order(d3.descending)

    vendedorTable.on('pretransition', function(table) {
      table.selectAll('td.dc-table-column')
        .on('click', function(d) {
          let filters = table.filters().slice();
          if (filters.indexOf(d.key) === -1)
            filters.push(d.key);
          else
            filters = filters.filter(k => k != d.key);
          if (filters.length === 0)
            vendedorDim.filter(null);
          else
            vendedorDim.filterFunction(function(d) {
              return filters.indexOf(d) !== -1;
            })

          table.replaceFilter([filters]);
          dc.redrawAll();
        });
      let filters = table.filters();
      table.selectAll('tr.dc-table-row')
        .classed('sel-rows', d => filters.indexOf(d.key) !== -1);
    });

    dc.renderAll();

  });

  $('#reset').on('click', function() {
    vendedorTable.filter(null);
    vendedorDim.filter(null)

    dc.redrawAll();
  });

  $('#resetTable').on('click', function() {
    vendedorTable.filter(null);
    vendedorDim.filter(null)

    dc.redrawAll();
  });

});
<head>
  <style>
    .dc-table-group {
      visibility: collapse;
    }
    
    tr.dc-table-row.sel-rows {
      background-color: lightblue;
    }
  </style>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
  <script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
  <script src="https://d3js.org/d3.v5.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"></script>

  <title>Vendedores</title>
</head>

<body>


  <div class="container-fluid">
    <div class="row content">
      <div class="col-md-8" style="padding-left: 20px;">
        <div class="row marginClass">
          <h4 class="pull-left" id="Introduction"><small>Dados fictícios da empresa | Exemplo de Pesquisa
                            Detalhada |
                        </small></h4>
          <h6 class="dc-data-count" style="float: left;margin-left:5px;">
            <span>
                            <span class="filter-count"></span> selected out of
            <span class="total-count"></span> records |
            <a id="reset"> Reset All </a>
            </span>
          </h6>
        </div>

        <div class="col-md-6">
          <br>
          <a id="resetTable"> Reset</a>
          <table class="table" id="Vendedores">
            <thead>
              <tr>
                <th>Sales</th>
                <th>Current Year</th>
                <th>Last Year</th>
              </tr>
            </thead>
          </table>
        </div>
      </div>
    </div>
  </div>
</body>

【问题讨论】:

    标签: javascript d3.js frontend dc.js crossfilter


    【解决方案1】:

    dc.js 是 crossfilter 的前端,它是一个针对 JavaScript 的内存数据库,针对此类仪表板进行了调整。

    您总是希望在数据库端添加数据。所以正确的地方是 crossfilter API,这里是:crossfilter.add()

    我可能刚刚发表了评论,但既然你已经足够好,可以包含运行代码,让我们试试吧!

    首先,让我们从数据集中保留一个供应商:

      rows = data0.filter(d => d.vendnm === 'JOÃO LUIS');
      var data = data0.filter(d => d.vendnm !== 'JOÃO LUIS');
    

    然后,当单击 Add Row 按钮时,让我们添加该数据并重新绘制所有关联的图表:

      $('#addRow').on('click', function() {
        myCrossfilter.add(rows);
        dc.redrawAll();
      });
    

    请注意,如果您多次单击“添加行”,该供应商的销售额将翻一番,然后是三倍,因为我们显示的是一个聚合组,因此该供应商获得的销售额越来越多。

    仅此而已!

    var vendedorTable = dc.dataTable("#Vendedores");
    // lift crossfilter and row so they are visible to addRow handler
    var myCrossfilter, rows;
    
    var url = 'http://www.json-generator.com/api/json/get/cgsUhkPSjS?indent=2';
    d3.json(url).then(function(data0) {
    
      // save Joao for later
      rows = data0.filter(d => d.vendnm === 'JOÃO LUIS');
      var data = data0.filter(d => d.vendnm !== 'JOÃO LUIS');
    
      data.forEach(function(d) {
    
        myCrossfilter = crossfilter(data);
        var all = myCrossfilter.groupAll();
    
        dc.dataCount(".dc-data-count")
          .dimension(myCrossfilter)
          .group(all);
    
        vendedorDim = myCrossfilter.dimension(function(d) {
          return d.vendnm;
        });
    
        var vendedorGroup = vendedorDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
    
        function reduceAdd(p, v) {
          p.totalAno += +v.Vendas_Ano;
          p.totalHomologo += +v.Vendas_Ant;
          return p;
        }
    
        function reduceRemove(p, v) {
          p.totalAno -= v.Vendas_Ano;
          p.totalHomologo -= v.Vendas_Ant;
          return p;
        }
    
        function reduceInitial() {
          return {
            totalAno: 0,
            totalHomologo: 0,
          };
        }
    
        // formatter = d3.format(".3s");
        // formatter2 = d3.format(".0%");
    
        //Fake Dimension
        rank = function(p) {
          return ""
        };
    
        function checkRows(d) {
          if (d.value.totalAno <= 0 || isNaN(d.value.totalAno) || d.value.totalHomologo <= 0 || isNaN(d.value.totalHomologo)) {
            return 0;
          }
          return d;
        }
    
        //vendedorTable
        vendedorTable.width(500)
          .height(480)
          .dimension(vendedorGroup)
          .group(rank)
          .columns([function(d) {
              d = checkRows(d);
              while (d != 0) {
                return d.key;
              }
            },
            function(d) {
              d = checkRows(d);
              while (d != 0) {
                return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
                  minimumFractionDigits: 2
                }) + '€';
              }
            },
            function(d) {
              d = checkRows(d);
              while (d != 0) {
                return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
                  minimumFractionDigits: 2
                }) + '€';
              }
            }
          ])
          .sortBy(function(d) {
            return d.value.totalAno
          })
          .order(d3.descending)
    
        vendedorTable.on('pretransition', function(table) {
          table.selectAll('td.dc-table-column')
            .on('click', function(d) {
              let filters = table.filters().slice();
              if (filters.indexOf(d.key) === -1)
                filters.push(d.key);
              else
                filters = filters.filter(k => k != d.key);
              if (filters.length === 0)
                vendedorDim.filter(null);
              else
                vendedorDim.filterFunction(function(d) {
                  return filters.indexOf(d) !== -1;
                })
    
              table.replaceFilter([filters]);
              dc.redrawAll();
            });
          let filters = table.filters();
          table.selectAll('tr.dc-table-row')
            .classed('sel-rows', d => filters.indexOf(d.key) !== -1);
        });
    
        dc.renderAll();
    
      });
    
      $('#reset').on('click', function() {
        vendedorTable.filter(null);
        vendedorDim.filter(null)
    
        dc.redrawAll();
      });
    
      $('#resetTable').on('click', function() {
        vendedorTable.filter(null);
        vendedorDim.filter(null)
    
        dc.redrawAll();
      });
    
      $('#addRow').on('click', function() {
        myCrossfilter.add(rows);
        dc.redrawAll();
      });
    
    });
    <head>
      <style>
        .dc-table-group {
          visibility: collapse;
        }
        
        tr.dc-table-row.sel-rows {
          background-color: lightblue;
        }
      </style>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
      <script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css">
      <script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
      <script src="https://d3js.org/d3.v5.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"></script>
    
      <title>Vendedores</title>
    </head>
    
    <body>
    
    
      <div class="container-fluid">
        <div class="row content">
          <div class="col-md-8" style="padding-left: 20px;">
            <div class="row marginClass">
              <h4 class="pull-left" id="Introduction"><small>Dados fictícios da empresa | Exemplo de Pesquisa
                                Detalhada |
                            </small></h4>
              <h6 class="dc-data-count" style="float: left;margin-left:5px;">
                <span>
                                <span class="filter-count"></span> selected out of
                <span class="total-count"></span> records |
                <a id="reset"> Reset All </a>
                </span>
              </h6>
            </div>
    
            <div>
                <a id="addRow"> Add Row </a>
            </div>
    
            <div class="col-md-6">
              <br>
              <a id="resetTable"> Reset</a>
              <table class="table" id="Vendedores">
                <thead>
                  <tr>
                    <th>Sales</th>
                    <th>Current Year</th>
                    <th>Last Year</th>
                  </tr>
                </thead>
              </table>
            </div>
          </div>
        </div>
      </div>
    </body>

    【讨论】:

    • 你好 Gordon,我想我明白你的解释了,我将创建一个带有总销售额的 crossfilter.add() 方法。顺便说一句,我已经学习 D3.js、DC.js 和 Crossfilter 几个月了,我意识到在 StackOverfllow 你可以帮助人们很多。这是在不到 36 小时内第二次指导我,感谢您。
    • 我刚刚在 stackoverflow 上发布了一个关于我在工作中遇到的挑战的问题。我已经为此工作了几个月,但我仍然无法解决它。如果您可以查看并给我任何提示/指导,我真的很感激!我被这个项目困住了,我不知道还能做什么。 stackoverflow.com/questions/59952879/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    相关资源
    最近更新 更多