Dynamically change the column name based on inputs - reactjs

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}
/>
);
}

Related

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-semantic-redux-form selectField multiple

I am attempting to use react-semantic-redux-form SelectField with the multiple options so a user can select multiple options and if there is one already set then this should show as checked.
I am also using redux-form with semantic0ui-react.
I am getting an error attempting to include multiple selections.
My include statement is:
import { SelectField } from "react-semantic-redux-form";
My state is:
state = {
relationships: ["some entry"],
relationshipOptions: [],
};
The element code is:
<Grid.Column>
<Field
component={SelectField}
name="relationships"
label="Your Relationships"
options={relationshipOptions}
multiple
placeholder="Select to add a relationship"
/>
I get the error as below
Dropdown `value` must be an array when `multiple` is set. Received type: `[object String]`.
in Dropdown
The way you have relationshipOptions is wrong, it is supposed array of objects,
const relationshipOptions = [
{ key: "single", value: "single", text: "single" },
{ key: "married", value: "married", text: "married" }
];
Here is the working example, Code Sandbox
Also if you have single, married in array. You can do something like this,
let relationshipOptions = ["single", "married"].map((x) => {
return ({
key: x,
value: x,
text: x
});
});

Fluent UI DetailsList - Is there a way to add filters to each column

I am using Fluent UI DetailsList. My table looks like below:
I need filters below every column (text or drop-down) as shown below:
Please let me know if this is possible? Or maybe a way to display custom header (using html) ?
This actually turned out to be easier than I thought it'd be...
If you're ok with clicking the column header to reveal the choices (vs having the dropdown directly under the title) then this can be achieved using the ContextualMenu component in conjunction with DetailsList. I got it working by tweaking from the variable row height example in the official docs: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/variablerowheights.
Add a ContextualMenu underneath your DetailsList:
<DetailsList
items={items}
columns={columns}
/>
{this.state.contextualMenuProps && <ContextualMenu {...this.state.contextualMenuProps} />}
Inside your column definition, set the hasDropdown action so the user gets a UI indicator that they can/should click the header, and call a contextMenu method (note I'm using onColumnContextMenu as well as onColumnClick so it doesn't matter if they left or right click the header:
{
key: 'dept',
name: 'Department',
fieldName: 'dept',
minWidth: 125,
maxWidth: 200,
onColumnContextMenu: (column, ev) => {
this.onColumnContextMenu(column, ev);
},
onColumnClick: (ev, column) => {
this.onColumnContextMenu(column, ev);
},
columnActionsMode: ColumnActionsMode.hasDropdown,
}
When the onColumnContextMenu method gets invoked, we need to build the context menu properties that will get consumed by the ContextualMenu component. Note the dismissal method as well, which clears out the state so the menu is hidden.
private onContextualMenuDismissed = (): void => {
this.setState({
contextualMenuProps: undefined,
});
}
private onColumnContextMenu = (column: IColumn, ev: React.MouseEvent<HTMLElement>): void => {
if (column.columnActionsMode !== ColumnActionsMode.disabled) {
this.setState({
contextualMenuProps: this.getContextualMenuProps(ev, column),
});
}
};
Finally, inside of getContextualMenuProps you need to determine what the options should be for the user to click. In this example, I'm simply giving sort options (you'll need to add an onClick handler to actually do something when the user clicks the item), but I'll use the column to determine what those items should actually be and paint the filters into the items collection so the user can select one to filter.
private getContextualMenuProps = (ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps => {
const items: IContextualMenuItem[] = [
{
key: 'aToZ',
name: 'A to Z',
iconProps: { iconName: 'SortUp' },
canCheck: true,
checked: column.isSorted && !column.isSortedDescending,
},
{
key: 'zToA',
name: 'Z to A',
iconProps: { iconName: 'SortDown' },
canCheck: true,
checked: column.isSorted && column.isSortedDescending,
}
];
return {
items: items,
target: ev.currentTarget as HTMLElement,
directionalHint: DirectionalHint.bottomLeftEdge,
gapSpace: 10,
isBeakVisible: true,
onDismiss: this.onContextualMenuDismissed,
}
}
Note the target on the ContextualMenuProps object, which is what tells the ContextualMenu where to lock itself onto (in this case, the column header that you clicked to instantiate the menu.
Detail list filter for each column without context menu -
https://codesandbox.io/s/rajesh-patil74-jzuiy?file=/src/DetailsList.CustomColumns.Example.tsx
For instance - Providing filter in text field associated with each column will apply filter on color column.

Configuring word-wrap in column header of an Antd Table

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.

Dynamically show/hide columns based on user selection with respect to react-table : React+Typescript

I am using react-table for as a data grid for an application . I have this scenario where I need to show/hide columns that are listed and based on user selection I need to show/hide them . Is there any way I can achieve this?
Basically need to have a some settings kind of icon , on click of the same I need to display all the available columns and based on the checkbox selection I need to show/hide them.
How can I get all the column values from react-table to show in this dropdown?
How can I add this settings icon as a part of column header(I will be displaying id's under this column), But the header for this column would be a settings icon next to "Edit" label
import * as React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
export default class App extends React.Component<{},{}>
constructor(props:any){
super(props);
this.state={
data : [];
}
componentDidMount() {
//using some fetch Call, I get the data and set it to state data property
let data = fetch(); // fetch call which is not described here
this.setState({data})
}
render(){
<ReactTable
data={this.state.data}
columns = {[
{
Header: "Edit",// here i need to add an settings icon next to "Edit" header and on click of the same need to show all the column names, then show/hide them based on selection
id: "row",
Cell: (row:any) => {
return <span>{row.index+1}</span>;
}
},
{
id: 'name,
Header: 'Name',
accessor: 'username',
},
{
id: 'dob,
Header: 'DOB',
accessor: 'userDOB',
},
{
id: 'status',
Header: 'Status',
accessor: 'userStatus',
}
]}
/>
}
}
The first issue I see is you are planning to store all column names in a Row 'Edit' -but the function
'(row:any) => { return {row.index+1}; }' is will iterate over data object - not columns object. That means, if data rows more then columns you are unnecessarily going over all the data rows.
Instead, store columns object state in React State. Update 'show' property of the columns to hide/show columns.
Something like this code here --
https://eim52.codesandbox.io/
This is a super low tech solution that I figured out, and not doing things dynamically, but perhaps this can help you achieve your goal:
To hide a column in a static way do the following:
1) Give the column a value of hidden, which will hide the column but not the column header.
2) Give the column an empty name or else you will see text in the header.
3) Give the column a width of -1. A width of 0 leaves a small empty header column, but -1 'hides' it apparently. Not sure why it works, im not a css master, but it works.
const columnTemplate = [
{
{
key: "costCenter",
name: "",
width: -1,
hidden: true
}
}
];

Resources