Dropdown with LIKE operator react-bootstrap-table2 - reactjs

I have a table that implements react-bootstrap-table2. They provide a custom way of doing external filter (out of the column header). In my table, the first column is a combination of data that I pass a string with # as separator and the format them with the formatter function as follow:
This is my column definition:
let projectFilter;
columns = [{
dataField: 'project',
text: 'Project',
filter: textFilter({
options: fpsoOptions,
getFilter(filter){
projectFilter = filter;
},
style: { display: 'none' }
}),
sort: true,
formatter: this.projectFormatter,
headerStyle: (col, idx) => {
return smHeaderStyle;
},
}, [..]
And this is the projectFormatter function:
projectFormatter = (cell, row) => {
const values = cell.split('|');
const fpsos = values[0].split('#');
return (
<div>
{fpsos.map((pu, idx) => {
const identity = pu.split(';')[0];
const id = pu.split(';')[1];
const separator = idx !== fpsos.length - 1 ? ", " : '';
return (
<Link to={`/view/${id}/fpso`}>{identity}{separator}</Link>
)
})}
<br/>
<span><b>{ values[1] }</b></span><br/>
</div>
);
}
The filtering works fine when it is a text input filter. Now, I'm trying to do a custom select filter with a LIKE operator behaviour, which the selected value in the dropdown (fpso list) would be filtered as a substring of this column.
This is my onChange function that triggers the table filter, as shown in the documentation here. But I'm not sure how to get the like behaviour.
const onChangeFilter = (e) => {
projectFilter(e.target.value)
}
I appreciate any clue/help. Thanks in advance

Related

react-table setFilter with custom filter function?

I am trying to set a filter on a column using react-table . I'd like a checkbox change to filter multiple possible values for one column.
Let's say I have a table like this. When the checkbox is checked - I want all instance to show. When not checked I want everything but instance checked.
const columns = useMemo( () => [
{
Header: 'col1',
accessor: 'col1'
},
{
Header: 'col2',
accessor: 'col2'
}
{
Header: 'col3',
accessor: 'col3'
}
], [] )
const {
...
setFilter,
filters,
} = useTable(
{columns, data},
useFilters
....
)
const onFilterChange= (e, value) => {
if(e.target.checked){
setFilter('col3', 'instance') //works!
}
else{
setFilter('col3', cell => cell.value !== 'instance' ) //does not work - how do I do this?
}
}
return (
<input
type="checkbox"
onChange={ e => onFilterChange(e, 'instance')}
/>
)
Can I pass a custom function into setFilter ? Not seeing how to do this with react-table

Semantic UI dropdown not setting value after selecting option

I am using React semantic ui. I am rendering a dropdown in Fieldset. I have written code such that, once a option is selected, the options is updated such that the selected option is removed from the list. But when I select an option from the dropdown, the selected value is not displayed, rather it shows empty.
Here is my code:
This is my dropdown code:
<Dropdown
name={`rows.${index}.mainField`}
className={"dropdown fieldDropdown"}
widths={2}
placeholder="Field"
fluid
selection
options={mainFieldOptions}
value={row.mainField}
onChange={(e, { value }) => {
setFieldValue(`rows.${index}.mainField`, value)
updateDropDownOptions(value)
}
}
/>
My options:
let mainField = [
{ key: "org", text: "org", value: "org" },
{ key: "role", text: "role", value: "role" },
{ key: "emailId", text: "emailId", value: "emailId" },
]
Also, I have:
const [mainFieldOptions, setMainFieldOptions] = useState(mainField)
And,
const updateDropDownOptions = (value:any) => {
let updatedOptions: { key: string; text: string; value: string }[] = []
mainFieldOptions.forEach(option => {
if(option.key != value){
updatedOptions.push({ key:option.key , text:option.key, value:option.key })
}
})
setMainFieldOptions(updatedOptions)
console.log("mainfield", mainField)
}
In onChange, if I dont call updateDropDownOptions() method, the dropdown value is set. But when I call the method, its giving blank value. Please help.
There are few changes required in your code,
You are pushing the entire initialValues when you are adding a row which is an [{}] but you need to push only {} so change your code to initialValues[0] in your push method.
Its not needed to maintain a additional state for the options. You can filter the options based on the selected option in other rows which is available in the values.rows .
Util for filtering the options
const getMainFieldOptions = (rows, index) => {
const selectedOptions = rows.filter((row, rowIndex) => rowIndex !== index);
const filteredOptions = mainField.filter(mainFieldOption => !selectedOptions.find(selectedOption => mainFieldOption.value === selectedOption.mainField));
return filteredOptions;
}
Call this util when rendering each row
values.rows.length > 0 &&
values.rows.map((row, index) => {
const mainFieldOptions = getMainFieldOptions(values.rows, index);
Working Sandbox

grouping the data based on one property antd table

I am trying to group the data currently its working for three, if i remove any one gender then i wont be able to get it the same design,
Basically if the state_name is same then it should be grouped into same even there is only one gender or more than one as shown below
Codesandbox
Figured out the issue, basically having a variable outside, when the sameKey repeats not setting the count making rowSpan as 0 so it will be hidden.
Logic
let sameKey;
const columns = [
{
title: "District",
dataIndex: "state_name",
key: "state_name",
render: (value, row, index) => {
const obj = {
children: value,
props: {}
};
if (!(sameKey !== value)) {
obj.props.rowSpan = 0;
return obj;
}
const count = data.filter(item => item.state_name === value).length;
sameKey = value;
obj.props.rowSpan = count;
return obj;
}
},
See the codesandbox

React.useMemo does not update the data

I am new to hooks. So this might be easy yet I have no idea how to solve:
I have a function like this which takes two arrays columns and data . and those data should be memoized or else it does not work. (recommended by react-table guys)
function ReactTable(props) {
const columns = React.useMemo(() => props.columns, [])
const data = React.useMemo(() => props.data, [])
return <Table columns={columns} data={data} />
}
this works fine but when the props change (say an item is added or removed from data array), the React.useMemo won't send the updated data to the Table component. How can I resolve this :(
This is exactly what the dependency array in hooks is for. You can define variables that 'trigger' the change on hooks. In your case this would mean that you would need to change your code to the following:
function ReactTable(props) {
const columns = React.useMemo(() => props.columns, [props.columns]);
const data = React.useMemo(() => props.data, [props.data]);
return <Table columns={columns} data={data} />
}
This means, whenever props.columns changes, the columns variable is updated and the same for props.data and data.
Mind you above answer from user Linschlager might not work if you're using react-table's sorting hook useSortBy. Indeed, the authors final solution did not involve react.useMemo.
To me it worked out anyways. My columns- and row-data came from a query-data object that I had to resolve to fit the specific way react-table does it.
It looked something like this:
function ReportTable({ queryData }) {
... other data such as {selectedPerLevel} ...
/* COLUMNS */
let firstColumn = {
Header: ' ',
columns: [
{
Header: selectedPerLevel.name,
accessor: 'perLevel',
},
],
};
let otherColumns = [];
queryData.weeks.forEach((week) => {
let otherColumn = {
Header: week,
Footer: ' ',
center: true,
columns: [
{
Header: 'Ratio',
accessor: `ratio${week}`,
},
{
Header: 'Count',
accessor: 'count' + week,
},
],
};
otherColumns = [...otherColumns, otherColumn];
});
/* ROWS */
let listOfRows = queryData.units.map((unit) => {
let row = {};
// for each column
unit.items.forEach(({ week, ratio, count}) => {
row = {
...row,
['ratio' + week]: ratio,
['count' + week]: count,
};
});
// add the first column-data to the row
row = { ...row, perLevel: unit.name, id: unit.id };
return row;
});
const data = React.useMemo(() => listOfRows, [queryData]);
const columns = React.useMemo(() => [{ ...firstColumn }, ...otherColumns], [queryData]);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({data, columns}, useSortBy);
return <Table ....
I don't know if this is to anyones help but it all worked out fine for me with above solution.

How to select text to copy without triggering click event in reactjs

I am using react-table. I have defined onRowClick() function for a column. Here select text should highlight the text and clicking have to redirect to another page. Now when I try to select the text, its getting redirected. How to select text without triggering click event?
Following is my onRowClick function:
onRowClick = (state, rowInfo, columnInfo) => {
return {
onClick: (e, handleOriginal) => {
if (columnInfo.id) {
this.props.history.push(`/downloads/${rowInfo.original.id}`);
} else if (handleOriginal) {
handleOriginal();
}
}
};
}
The following is my react-table component:
<ReactTable
manual
getTdProps = {this.onRowClick}
data = {results}
onFetchData = {this.onFetchData}
sortable = {false}
showPagination = {false}
noDataText = 'no data found'
columns = {[
{
Header: 'Id',
maxWidth: 50,
accessor: "id",
Cell: (props) => <span className="btn-link pointer">{props.value} </span>
},
{
Header: 'Processed on',
maxWidth: 165,
accessor: "created_at",
Cell: (props) => <span> {this.getDateTime(props.value)} </span>
}
]
/>
Clicking on id column should redirect to the details page. Selecting text should select the id text.
I think onclick cannot be prevented but your desired result can be obtained by using Window.getSelection() method.
The Window.getSelection() method returns a Selection object representing the range of text selected by the user or the current position of the caret.
By using this method you can get the selected text and then you can calculate its length as:
window.getSelection().toString()
And then you can modify your onRowClick method as given below:
onRowClick = (state, rowInfo, columnInfo) => {
return {
onClick: (e, handleOriginal) => {
let selection = window.getSelection().toString();
if(selection.length <= 0) {
if (columnInfo.id && selection.length > 0) {
console.log("columnInfo.id", columnInfo.id);
this.props.history.push(`/downloads/${rowInfo.original.id}`);
} else if (handleOriginal) {
handleOriginal();
console.log("columnInfo.id", "nothing");
}
}
}
};
};
I have created a working demo.

Resources