Configuring word-wrap in column header of an Antd Table - reactjs

I already spent too much time searching on how to configure the column headers of Antd tables, in the official Antd table docu and elsewhere, but I was not successful: Is there a simple way of adjusting the word-wrap of the column header?
Right now, if the column is too small (e.g. when resizing the browser window), letters are floating into new lines in an uncontrolled manner. English hyphenation would be cool, but for a start I would appreciate having 2 or 3 ellipsis dots instead of freely dropping characters.
Any Antd-experts out there who could help me out, please?
Minimal non-working example
import { Table } from "antd";
const { Column } = Table;
const dataSource = [
{
key: '1',
name: 'Mike',
},
{
key: '2',
name: 'John',
},
];
const columns = [
{
title: 'My very-very-very long column-name',
dataIndex: 'name',
key: 'name',
},
];
<Table dataSource={dataSource} columns={columns} />;
Related questions
Overwriting a single (nested) property when extending a React class is the more general problem I am facing.
How can we configure the Header of ant design table component?
Customize React Antd table header with table data

Table.Column.title accepts a ReactNode, so you only need to render an Ellipsis component.
You should use antd built-in Ellipsis, for that use Typoghrapy API.
Note: You should strain container's width so the ellipsing will work:
const COLUMN_STYLE = { width: 200 };
<Typography.Text ellipsis={true} style={COLUMN_STYLE}>
A very long text
</Typography.Text>
You can achieve the same effect with pure CSS, refer to text-overflow.
const dataSource = [
{
key: '1',
name: 'Mike'
},
{
key: '2',
name: 'John'
}
];
const COLUMN_STYLE = { width: 200 };
const customColumn = {
title: (
<Typography.Text ellipsis={true} style={COLUMN_STYLE}>
My very-very-very long column-name My very-very-very long column-name My
very-very-very long column-name
</Typography.Text>
),
dataIndex: 'name',
key: 'custom'
};
const normalColumn = {
title: 'My very-very-very long column-name',
dataIndex: 'name'
};
const TOTAL_COLUMNS = 6;
const columns = [...Array(TOTAL_COLUMNS).keys()].map(key => ({
...normalColumn,
key
}));
const App = () => (
<Table dataSource={dataSource} columns={[customColumn, ...columns]} />
);

Since I am (yet) stuck with an old version of Antd, I went the inline-CSS way suggested by Dennis Vash. Within the render() function, I defined
var myColTitleStyle = {
textOverflow: 'ellipsis',
// overflow: "hidden",
whiteSpace: 'nowrap'
};
Interestingly, I had to comment the parameter overflow out, although https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow suggests that it is required for the property text-overflow to work. Also note the CamelWritingStyle of the css-properties within React.
Inside the component, the imports are
import { Table } from "antd";
const { Column, ColumnGroup } = Table;
The actual call of Antd's Column contains a <div> within the title, plus the inline-CSS:
<Column
title={<div style={myColTitleStyle}>My long-long title</div>}
width=10
>
Please also note that textOverflow will only work with absolute widths, which are dimensionless in React. It will not work when using percentage-widths.

Related

Dynamically use React Component based on data in an object

I'm creating this menu as a fun project in React, and I've finished the code to display/style the components, so now I'm setting it up to be dynamic and generate the menu based on a passed set of data. My React project routes like this:App /→Tab /→Various components based on data.
The plan is to have a menu (App/) contain potentially multiple Tab / of various inputs, such as date, text, number, range, etc. Let's say I use this dataset as an example:
elements: [
{
type: 'number',
text: 'Some Text Label',
fields: [
{
text: 'Some Text',
min: 0,
max: 50,
value: 25,
},
{
text: 'Some Text',
min: 25,
max: 75,
value: 50,
},
],
},
{
type: 'text',
text: 'Some Text Label',
fields: [
{
text: 'Some Text',
value: 'Some Text Placeholder',
},
],
},
{
type: 'number',
text: 'Some Text Label',
fields: [
{
text: 'Some Text',
min: 0,
max: 100,
value: 50,
},
],
},
]
Within the Tab / component, I'd want to look through the elements to find the type of one element, then use the component that is ready for that element (for example, type:number, I would use Number / and then pass the fields as a prop to that component.
Something like this:Number fields={insertdatahere}/>
I'm a total beginner when it comes to react, but I've tried a few ways myself and I feel like I'm just missing something because nothing is working. I was considering just having all the Components manually placed inside the tab component and having them set as Display: None unless an element is present for that type. Thanks for any advice.
Here's a Code sandbox which illustrates one way you could get started.
The basic idea is to define a component for each type of field (text, number, ...) and make a lookup. A function component is like any other value in Javascript - you can store it in an array or an object.
In this case I've defined TextDisplay and NumberDisplay:
const TextDisplay = ({ text, value }) => (
<li>
<h4>{text}</h4>
<input value={value} />
</li>
);
const NumberDisplay = ({ text, min, max, value }) => (
<div>
<h4>{text}</h4>
<input type="number" min={min} max={max} value={value} />
</div>
);
const ComponentForType = {
text: TextDisplay,
number: NumberDisplay
};
Then there's a bit of machinery for displaying the lists of elements in the definition, and the list of fields in each element.
Hopefully that can give you something to play around with. There's a bit of weird syntax in there like the spread operator, and everything gets complicated once you want to make the values editable, but this could be a starting point.

TanStack react table v8 style each cell based on the cell value

We are migrating our tables from v7 to v8. And I'm kinda got a problem with cells conditional styling.
So basically what I want to do is, based on a status (which is coming to table data) I need to add a specific className to every cell in a row.
In v7 we used this: https://react-table-v7.tanstack.com/docs/examples/data-driven-classes-and-styles
But in v8 I can't find anything like that....
So far I tried to use meta in column definitions https://tanstack.com/table/v8/docs/api/core/column-def#meta where I can set some values to className property, and use it in my JSX like this:
className={cell.column.columnDef.meta?.className}
But problem is anything I can set to meta are static values. For my case I need to set specific className based on my status value. And seems like in meta we can't access any cell props...
const driverFormatter = ({ row }) => {
const { status } = row.original;
return <span>{status}</span>;
};
const columns: ColumnDef<any,any>[] = [
{
accessorKey: "customerName",
header: "Customer"
},
{
accessorKey: "driver",
header: "Driver",
enableSorting: false,
cell: driverFormatter,
meta: {
className: "disabled",
},
},
...
So is there are any way of achieving that using v8???
Thank you!

Custom data attributes on Fluent UI dropdown

I have a requirement to add custom data attributes to the Fluent UI dropdown.
In javascript/html I could add them like this.
option data-passign="true" data-minpt="3" data-maxpt="6" value="7">Data Quality</option
Can someone help me achieve this in Fluent UI + React?
In FluentUI/React, it's much easier than that, no need for data- attributes, you can just add your custom data directly to the options list (and get it back in the event handlers, or as the selected value if you are using "controlled" scenario). Means, if you don't have a specific requirement to store additional item data in the HTML data attributes for "something else" (like ui-automation tool), then you could go with something like this (note the data property):
const YourComponent = (props) => {
const options = [
{ key: '7',
text: 'Data Quality',
data: { passign: true, minpt: 3, maxpt: 7 }
},
{ key: '42',
text: 'Weather Quality',
data: { passign: true, minpt: 100500, maxpt: 42 }
},
];
const onChange = (evt, item) => {
const itemData = item.data;
console.log(item.key, item.text, itemData);
};
return (
<Dropdown
label="Select something"
options={options}
defaultSelectedKey='7'
onChange={onChange}
/>
);
}
If you want a "controlled" control instead (this one is "uncontrolled"), check out the sample page for the Dropdown:
https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown

React Datagrid with cards instead of columns?

We love the DataGrid for its build in sorting and filtering capabilities.
However grid based layouts are troublesome on small screen devices. So we started looking at Card based layouts. There we miss the sorting and filtering we appreciate in the DataGrid.
Now we are wondering if there is an example to use cards as UI layer for the DataGrid, where a column in the grid would become a row in the card. Cards should flow to available columns.
How can we do this?
This is a partial answer, however, there is a renderCell prop in the column configuration that accepts a function that can include a component.
So, to replace a row with a card, I might include a column that renders your components with all of the values you would otherwise express one by one in a series of columns. For instance:
const columns = [
{ field: 'id', headerName: 'ID', hide: true }, // keep this
{ field: 'myCombinedView', hide: false, flex: 1, renderCell: (props) => <Component {...props} /> },
I can imagine including a single, hidden column that represents a concatenation of the values you want to sort on. From here, specify the sort function for the Component column that uses the hidden value.
The following code sample is pulled from the DataGrid storyboard:
() => {
const columns = getColumns();
// compute a new field for purposes of sorting
columns[columns.length] = {
field: 'username',
valueGetter: (params) =>
`${params.getValue('name') || 'unknown'}_${params.getValue('age') || 'x'}`,
sortComparator: (v1, v2, cellParams1, cellParams2) => cellParams1.row.age - cellParams2.row.age,
width: 150,
};
return (
<div className="grid-container">
<XGrid
rows={getRows()}
columns={columns}
// use the field as the sort model
sortModel={[{ field: columns[columns.length - 1].field, sort: 'asc' }]}
/>
</div>
);
}
How to dynamically select/change the sort criteria is not something I can see a clear path for.

Dynamically change the column name based on inputs

I'm using Office UI fabric Detail List component (https://developer.microsoft.com/en-us/fabric#/controls/web/detailslist). Is it possible to change the Column header name based on inputs to the Detail List?
I found a way to change the Footer(https://developer.microsoft.com/en-us/fabric#/controls/web/detailslist/customfooter) but not Header since DetailsHeader doesn't have onRenderItemColumn props in it.
Any help?
The DetailsColumn component seems to always render the column's name property value: https://github.com/OfficeDev/office-ui-fabric-react/blob/master/packages/office-ui-fabric-react/src/components/DetailsList/DetailsColumn.base.tsx#L122.
Thus, I think you have to dynamically regenerate a new array of IColumn definitions each time your "inputs" change inside the render call of your component.
MyComponent:
state = { replaceSpaces: false, spaceReplacementChar: '_' };
columns = [{ name: 'Column 1', minWidth: 100, ... }];
...
getColumns(state) {
return this.columns.map((column) => {
return {
...column,
name: state.replaceSpaces
? column.name.replace(/\s/g, state.spaceReplacementChar)
: column.name
};
});
}
...
render() {
return (
<DetailsList
columns={this.getColumns(this.state)}
{...this.othertableProps}
/>
);
}

Resources