简体   繁体   中英

AG Data Grid table: generate a Vega-Lite chart that updates automatically

I would like to use Ag Data Grid filtered data to generate plots in Vega-Lite that update automatically whenever the filter(s) are changed. I would prefer to have the implementation in an observablehq notebook. Here is a section on how to access the table data in Ag Grid documentation. I created an observablehq notebook where the chart is updated using a button. There are two issues with this implementation:

  1. The chart is generated only after the button is clicked.
  2. I would prefer the chart update to be automatic without the need to click a button.

Thanks for linking to the notebook, It appears that the angular table does update. but it appends to the element and gets drawn behind the code cells: This is what it looks like in my browser when I move the slider:

在此处输入图像描述

The problem with components like this that manipulate the DOM is that they work against Observable's way of managing the DOM. Even if the component were to update correctly, it would probably still not resize the way you'd expect.

Observable is already reactive at its core, which is something angular (and other frameworks like React) was built to add to JavaScript. Using Observable's built-in reactivity will be much easier in the long run than trying to make two different reactivity models work with each other.

You can make the AG Grid table an Observable “ view ” so that you can both (1) see the table and (2) refer to its value in other cells, which will re-run when you filter the table. Once you do that, it'll work naturally with anything else you want to do in the notebook. Here's a working example with Observable Plot , and here's the same example with Vega-Lite .

Assuming you've loaded AgGrid and have gridOptions in a different cell, you can wrap AgGrid as an Observable view like this:

viewof table = {
  const node = htl.html`<div style="height:320px;" class="ag-theme-alpine"></div>`;
  
  new AgGrid.Grid(node, gridOptions);
  gridOptions.api.addEventListener("modelUpdated", update) // set value after filter
  gridOptions.api.sizeColumnsToFit();
  update(); // set initial value

  function update() { // for Observable dataflow
    let value = [];
    gridOptions.api.forEachNodeAfterFilter(d => value.push(d.data));
    node.value = value;
    node.dispatchEvent(new Event("input"));
  }
  
  return node;
}

A few notes on how this is different from your version (as of when I saw it):

  • I put the HTML and the AgGrid initialization in the same cell, so that AgGrid has an object reference to the node and if you re-run the cell it all gets cleaned up and recreated as a whole.
  • I listen for when the grid rows change with gridOptions.api.addEventListener("modelUpdated", update) .
  • In that update function, I do the same iteration over the rows that you were doing to build an array, but then I set it as the value of the node, and dispatch an input event from that node. That's what Observable looks for to tell when a view has changed its value and other cells should re-run.
  • I name the cell viewof table . You might've seen this pattern with sliders and other inputs on Observable. The viewof keyword means that you get the DOM node rendered, but you can also refer to its value with just table in other cells.

Thanks for the question; I've been meaning to check out AG Grid for a while!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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