Dynamic Clarity DataGrid with Unknown Data Set - datagrid

I am working with variable data sets and I can barely predetermine the data columns until the data is fetched from the API service. I have worked out a way to render the clarity datagrid ("#clr/angular": "4.0.8") dynamically as follows:
private fetchSiloData(uuid: string) {
const sub = this.siloService.getSiloData(uuid).subscribe({
next: resp => {
this.siloData = resp;
// extract columns from the data and mark the first 5 columns as visible for datagrid columns
if (resp.length) {
this.columns = Object.keys(resp[0]).map((key, index) => {
if (index < 5) {
return { name: key, hidden: false };
}
return { name: key, hidden: true };
});
}
},
complete: () => {
if (sub) {
sub.unsubscribe();
}
},
});
}
In my component html, I have the following:
<clr-datagrid>
<clr-dg-column *ngFor="let col of columns" [clrDgField]="col.name">
<ng-container *clrDgHideableColumn="{ hidden: col.hidden }">
{{ col.name }}
</ng-container>
</clr-dg-column>
<clr-dg-row *clrDgItems="let row of siloData" [clrDgItem]="row">
<clr-dg-cell *ngFor="let col of columns">{{ row[col.name] }}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }} of
{{ pagination.totalItems }} rows
<clr-dg-pagination #pagination [clrDgPageSize]="20"></clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>
With the above, my expectation was to:
Get a neatly formatted datagrid as would if I had knowledge of my data columns
The clarity datagrid to automatically hide data cells corresponding to hidden columns
Selecting and unselecting columns to work.
However here is my result with a sample data source:
I even went ahead to create a pure pipe to filter out data cells with hidden columns and the effect of that is I now get a better initial view as far as cell count is concerned.
<clr-dg-row *clrDgItems="let row of siloData" [clrDgItem]="row">
<clr-dg-cell *ngFor="let col of columns | visibleColumns">{{
row[col.name]
}}</clr-dg-cell>
</clr-dg-row>
How do I go about my need for a dynamically rendered datagrid but still be able to have the datagrid column selection functionality work as expected? Or rather, how do I go about extending the datagrid to cover my use case? Thank you in advance.

Related

React-Table display contents of array as individual elements inside a cell

I am trying to use react-table to visualise some data structured as below:
{
companyName: "Barclays Bank Plc",
tenancies: ["G.01 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
{
companyName: "Boeing AerospaceLtd",
tenancies: ["G.01 # Newbuilding", "G.02 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
My column definition (which doesn't work) looks something like this:
{
Header: "Tenancies",
accessor: "tenancies",
Cell: (tableProps) => (
<div>{tableProps.cell.value.forEach((item) => item)}</div>
),
},
What I am trying to do is display each array item within it's own HTML tags (such as a div) so I can visually style and seperate them within the table cell.
Can anyone point me in the right direction as to the best way to achieve this?
According to the API document, the Cell receives the table Instance and returns a valid JSX.
{
...
Cell: (tableInstance) => JSX
}
Since the tenancies array are available from tableInstance.row.original.tenancies, so you can change your tenancies column definition as follow:
{
Header: "Tenancies",
Cell: ({ row }) => {
return (
<div>
{row.original.tenancies.map((tenancy, i) => (
<div key={i}>{tenancy}</div>
))}
</div>
);
}
}
Here is the example:

How can you disable specific Material-UI DataGrid Column Menu options?

I know that 'disableColumnMenu' will disable the entire column, and setting 'sortable' and 'filterable' to false will remove those options for that column. Is there a way to disable specific menu options, or otherwise modify the column menu? I want to keep the columns sortable and filterable, but remove the 'show' and 'hide' options.
To remove the "Show"-columns and "Hide" menu items from the column menu, I just added the disableColumnSelector to the DataGrid Component as show in the code image below.
You can do this by creating a custom menu and only including the filter and sort menu options.
// Assuming other imports such as React...
import {
GridColumnMenuContainer,
GridFilterMenuItem,
SortGridMenuItems
} from '#material-ui/data-grid';
const CustomColumnMenu = (props) => {
const { hideMenu, currentColumn } = props;
return (
<GridColumnMenuContainer
hideMenu={hideMenu}
currentColumn={currentColumn}
>
<SortGridMenuItems onClick={hideMenu} column={currentColumn} />
<GridFilterMenuItem onClick={hideMenu} column={currentColumn} />
</GridColumnMenuContainer>
);
};
export default CustomColumnMenu;
Then, use it in your grid like so:
// Assuming imports are done including DataGrid, CustomColumnMenu, and React...
<DataGrid
// Assuming: rows, rowHeight, etc...
components={{
ColumnMenu: CustomColumnMenu
}}
/>
There is also a prop disableColumnSelector={true} (passed to DataGrid component), however it will disable column selection for all columns, not only 1 specific column header.
You can do this by using the hideable field in the columns definitions.
const columns: Array<GridColDef> = [
{
field: 'foo',
hideable: false
},
// ... other cols
]
<DataGrid columns={columns} rows={rows} />

How to specify column width for first column using react-table

When using useRowSelect and useTable how can I specify column width for the first column so that it never exceeds the width of the checkboxes? I don't want to use useFlex as I want to preserve column widths based on the header width.
You'll notice when the table is set to 100% width the first column starts to grow if you expand your browser window.
Here's an example:
https://codesandbox.io/s/youthful-hamilton-j0rev?file=/src/App.js
I'm also open to just grabbing the Header and Cell from where I'm pushing into the columns array and adding a className, but wasn't able to find a way to do that. How can I add a className so that the table cell that surrounds this column data has a className to attach to:
(hooks) => {
isRowSelectable &&
hooks.allColumns.push((columns) => [
{
id: 'selection',
minWidth: 35,
width: '35px',
maxWidth: 35,
Header: ({ getToggleAllRowsSelectedProps }) => (
<Checkbox alignSelf="center" {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }: any) => {
row.className = '123';
return <Checkbox alignSelf="center" {...row.getToggleRowSelectedProps()} />;
}
},
...columns
]);
}
Since Array.map can pass the index of the element, it's fairly simple to conditionally add a className to the cell if the row index is 0:
{
rows.map((row, i) => {
prepareRow(row);
return (
<td className={i === 0 ? "class-name" : ""} {...cell.getCellProps()>
{cell.render("Cell")}
</td>
) ​
}
If you want the same class to apply to the headers, you can do the same thing on the <th> or <tr> elements, since those are also rendered with Array.map. You don't actually need to touch the columns object at all for this change.

Modify Bootstrap DataTable

I used an example of bootstrap datatable to have a sortable table on my symfony project. I use datatables.net
With this javascript code :
$(document).ready(function() {
$('#datatable').DataTable();
} );
And my table in HTML :
<table id="datatable" class="table table-striped">
<thead>
<tr>...
The only problem is that I don't want all my columns to be sortable (some columns only contain a checkbox or a button for example). Moreover with this table and this javascript code I automatically have a search bar as well as Previous Next buttons and other options that appear automatically. I would like to be able to modify this default template by removing all these options that I don't need. Do you have an idea how to adapt this datatable?
Thanks in advance
You should read documentation for datatables. https://datatables.net/extensions/rowreorder/examples/initialisation/restrictedOrdering.html
Example:
// add class reorder on column, that you want to order
$(document).ready(function() {
var table = $('#example').DataTable( {
rowReorder: true,
columnDefs: [
{ orderable: true, className: 'reorder', targets: 0 },
{ orderable: false, targets: '_all' }
]
} );
} );

Meteor C3 charts based on D3 - multiple charts?

EDIT: clone this repository for a non working reproduction. https://github.com/FickleLife/meteor-c3-test
I am using https://github.com/peernohell/meteor-c3.js/
I pull two examples off the C3 site http://c3js.org/examples.html and can get them to display once on the page, but when I try to add a second on the same page the first disappears. There's no console error and the javascript variables are different.
chart 1 html template:
<template name="chart_cp_overview">
<div id="cpOverview"></div>
</template>
chart 1 js helper:
Template.chart_cp_overview.rendered = function () {
var cpOverview = c3.generate({
data: {
columns: [
['data1', 30, 200],
['data2', 130, 100]
],
type: 'bar',
groups: [
['data1', 'data2']
]
},
grid: {
y: {
lines: [{value:0}]
}
}
});
}
chart 2 html template:
<template name="chart_status">
<div id="chart"></div>
</template>
chart 2 helper:
Template.chart_status.rendered = function() {
var chart = c3.generate({
data: {
columns: [
['Dropped', 30],
['On Course', 120],
['DNS', 20],
['Finished', 40]
],
colors: {
'Dropped': '#E60000',
'On Course': '#00ACED',
'DNS': '#DBDBDB',
'Finished': '#00BD07'
},
type : 'donut',
onclick: function (d, i) { console.log("onclick", d, i); }
// onmouseover: function (d, i) { console.log("onmouseover", d, i); },
// onmouseout: function (d, i) { console.log("onmouseout", d, i); }
},
donut: {
title: "Entrant Status",
label: {
format: function (value, ratio) {
return value;
}
}
}
});
};
display code :
<div class="row">
<div class="col-md-6">
{{> chart_cp_overview}}
</div>
<div class="col-md-6">
{{> chart_status}}
</div>
</div>
This code above displays only the last chart - chart_status. If I remove any one of the handlebars reference the other chart displays fine, or if I have multiple handlebars to multiple charts whatever was last declared is displayed.
How can I get multiple charts to display within one page? Example is on github at https://github.com/FickleLife/meteor-c3-test
It looks like maybe you are intending the two variable names you have chosen in your template rendered functions, cpOverview and chart, to bind to the dom elements with those ids. It won't work that way.
The variable names you have chosen are local to their functions and in any case would not automatically attach to elements with that id even if they were global. So c3 is binding all these charts to the same dom element (the docs say the default is #chart), and the last one is overriding the prior ones.
You want to bind each chart to its respective element. You can use this.firstNode inside your rendered function (based on the way you have it set up), or use jquery, or this.find("div#cpOverview"), and then use the c3 api to bind the chart to it - it looks like { bindto: "div#cpOverview" } may be the one you want.

Resources