Programmatically Filter with function component, impossible to get the filter - react-bootstrap-table-2 - react-bootstrap-table

I'm trying to implement a custom filter using react bootstrap table 2 in a function component, but when I use the getFilter function to get access to the filter, the setFilter didn't work and filter.text stay at null
const ExempleTable = () => {
const [filter, setFilter] = useState({ text: null });
const columns = [{
dataField: 'text',
text: 'Text',
filter: textFilter({
getFilter: (textFilter) => setFilter({ text: textFilter }),
})
}];
const setTextFilter = (e) => filter.text && filter.text(e.currentTarget.value);
return (
<>
<input onChange={setTextFilter} />
<BootstrapTable
filter={filterFactory()}
data={[{ text: "Je suis un test"}]}
columns={columns}
/>
</>
);
}
Here filter.text is always at null even after the setFilter. Is it possible to do it like that and to make it work ? Is there any workaround to make a programmatically filter inside a function component ?

As far as I know, getFilter is intended to gain access to the filter implemented by react-bootstrap-table-2, and not to overwrite it. So, if you do something like this:
const columns = [{
dataField: 'text',
text: 'Text',
filter: textFilter({
getFilter: (textFilter) => { this.setFilter = textFilter; },
})
}];
Then, you can later use this setFilter function to programmatically set the column filter by invoking the function like this:
invokeFilterFunction = (e) => {
this.setFilter(e.currentTarget.value);
}
return (
<>
<input onChange={invokeFilterFunction} />
<BootstrapTable
filter={filterFactory()}
data={[{ text: "Je suis un test"}]}
columns={columns}
/>
</>
);
If you want to overwrite the column filter function, I think you should use onFilter instead. According to the Storybook, you can define your own filter function, like this:
myOwnFirstFilter = (filterVal, data) => {
if (filterVal) {
return data.filter(text => text && text.indexOf(filterVal) !== -1);
}
return data;
}
And then, set the filter in the column like this:
const columns = [{
dataField: 'text',
text: 'Text',
filter: textFilter({
onFilter: this.myOwnFirstFilter,
})
}];

Related

React-admin SelectInput occurs out of range warning

I have SelectInput inside of ReferenceInput
As you can see below,
This is workaround version of code. the selection shows right data and it parses as I expected, however, a out-of-range value **[object Object]** is show. (please see the reference image below)
This is a code snippet of SelectInput component
const AddressSelectInput: FC<AddressSelectInputProps> = (
{
customerId,
source,
...props
}
) => {
const classes = useStyles()
const [choices, setChoices] = useState<InputSourceProps[] | undefined>()
// sorting data from props
useEffect(() => {
if (props.choices) {
const result: InputSourceProps[] | undefined = props.choices?.find(
item => item._id === customerId
)?.addresses?.map((item: UserAddress) => {
let res: InputSourceProps;
res = {
name: item.label,
description: item.place.description,
postalCode: item.place.postalCode,
location: {
lat: item.place.location.lat,
lng: item.place.location.lng
}
}
return res;
})
setChoices(result)
}
}, [props.choices, customerId])
if (!choices) {
return null
}
const optionRenderer = (choice: Place) => `${choice.name} - ${choice.description}`;
return (
<SelectInput
className={classes.selectInputStyle}
label="Addresses suggestion"
choices={choices}
source={source}
optionText={optionRenderer}
optionValue={'name'}
defaultValue=''
parse={(name: string) => choices.find(c => c.name === name)}
/>
)
}
this is parent component of SelectInput:
const RideReferenceAddressInput: FC<RideReferenceInputProps> = ({
source,
label,
customerId,
}) => {
const filterToQuery = (customerId: string) => (filter: string) => ({
$search: filter,
_id: customerId
})
return (
<ReferenceInput
reference="users"
source={source}
filterToQuery={filterToQuery(customerId)}
>
<AddressSelectInput source={source} label={label} customerId={customerId} />
</ReferenceInput>
)
}
Could anyone can help to remove the warning? and why this is warning shows?
Thank you all in advance!

`react-native-dropdown-picker` not selecting default value for multiSelect, if list item having selected:true {label:"A", value:1, selected:true}

I am trying to use multiselect feature of react-native-dropdown-picker which is working fine for selecting item, I can select multiple Items and can get its values too, but my problem is I am not able to show defaultValue on screen load.
I am fetching data from server and then trying to show on dropdown-picker
const AccountSelection = (props) => {
const [accountId, setAccount] = useState([])
const [accountList, setAccountList] = useState([])
const [defaultAccount, setDefaultAccount] = useState([])
useEffect(() => {
getAccounts()
}, [])
const getAccounts = () => {
axiosConfig.get('/accounts')
.then((response) => {
if (response.status == 200) {
const accountData = response.data.payload.data
const accountNames = accountData.map((item) => ({ label: item.name, value: item.id, selected: item.id == store.usersDefaultValues.account_id ? true : false }))
setAccountList(accountNames)
setDefaultAccount(accountNames.find(item => item.selected == true ? item.value : null))
}
}
})
.catch((error) => {
console.log("axios error", error);
})
}
return (
<View>
<DropDownPicker
placeholder="Select Account"
value={accountId}
items={accountList}
onChangeItem={(val) => setAccountId(val)}
defaultValue={defaultAccount}
multiple={true}
activeItemStyle={{ backgroundColor: '#F5CCF8' }}
></DropDownPicker>
</View>
)
}
On screen Load I am getting blank dropdown-picker, where it should show 1 Item Selected.
In DropDownPickerProps in react-native-dropdown-picker optional selected key is available but it is not working
items: {
label: any;
value: any;
icon?: () => JSX.Element;
hidden?: boolean;
disabled?: boolean;
selected?: boolean;
}[];
Please share if anyone have solution for this. Thank you.
The defaultValue attribute is not longer supported in react-native-dropdown-picker. If you want to select a default value, you simply need to set the 'value' variable to the default value's value.
You can read more in this issue: https://github.com/hossein-zare/react-native-dropdown-picker/issues/511#issuecomment-1049110163.

React-Admin: implementing dependant filters

I'm working on a react-admin page where I want to display some filters depending on the values of another one. To do so, I'm using the filterValues from the ListContext and simply show/hide the dependant filters:
const PostFilter = (props) => {
const { filterValues } = useListContext();
const { mainType } = filterValues;
return (
<Filter {...props}>
<SelectInput
source="mainType"
alwaysOn
choices={[
{ id: "type_1", name: "Type 1" },
{ id: "type_2", name: "Type 2" },
{ id: "type_3", name: "Type 3" }
]}
/>
{mainType === "type_1" && (
<SelectInput
source="type1"
alwaysOn
choices={[
{ id: "type_1_a", name: "A" },
{ id: "type_1_b", name: "B" },
{ id: "type_1_c", name: "C" }
]}
/>
)}
{mainType === "type_2" && (
<SelectInput
source="type2"
alwaysOn
choices={[
{ id: "type_2_a", name: "A" },
{ id: "type_2_b", name: "B" },
{ id: "type_2_c", name: "C" }
]}
/>
)}
</Filter>
);
};
This visually works fine but if I choose a value in one of the child filter and then change the main filter, the url is still containing the filter value even though it's not on screen anymore. As the url contains a wrong filter, then the list is not filtered properly.
To workaround this, I played with a useEffect and the setFilters function but it feels super hacky:
const { filterValues, displayedFilters, setFilters } = useListContext();
const { mainType } = filterValues;
// we need this workaround because these 3 values are not stable
// and get be used as the effect dependencies. However, we still want to be sure
// to always reference their latest version
const refs = React.useRef({ filterValues, displayedFilters, setFilters });
React.useEffect(() => {
refs.current = { filterValues, displayedFilters, setFilters };
});
React.useEffect(() => {
const filters = { ...refs.current.filterValues };
if (mainType !== "type_1") {
delete filters.type1;
}
if (mainType !== "type_2") {
delete filters.type_2;
}
refs.current.setFilters(filters, refs.current.displayedFilters);
}, [mainType]);
Here's a sandbox showing the result: https://codesandbox.io/s/hidden-mountain-i62p3?file=/src/posts.js
Is there a better way to achieve what I want?

How to hide button after pressing in material-table

I am using react material-table. I am in need of a feature like this: I use remote data mode to get a list of records, then I use the custom column rendering function to add a Material Button at the end of each row in the table, When the user presses this button I want it to be hidden. How can I do that. I look forward to receiving your help.
This is the illustration image
I made this example, on button click it gets disabled and a variable is set to to a loading state:
The key aspect here is to define something that identifies the row that is being updated. I use an extra column on which you could also display a spinner component:
{
field: "isUpdating",
render: (rowdata) =>
fetchingClient === rowdata.name
? "loading.." // Add your <Spinner />
: null
},
Since you want to render the button as a custom column (other way could be using actions), on the render attribute of that column, you can use rowdata parameter to access what you are looking for:
{
field: "join",
sorting: false,
render: (rowdata) => (
<button
disabled={fetchingClient === rowdata.name}
onClick={(event) => fetchDataFromRemote(rowdata.name)}
>
Go fetch
</button>
)
}
Here is the link to the sandbox and the complete code, I hope this works for you!
import React, { Fragment, useState } from "react";
import MaterialTable from "material-table";
export default function CustomEditComponent(props) {
const [fetchingClient, setFetchingClient] = useState("");
const fetchDataFromRemote = (clientName) => {
console.log(clientName);
setFetchingClient(clientName);
};
const tableColumns = [
{ title: "Client", field: "client" },
{ title: "Name", field: "name" },
{
field: "isUpdating",
render: (rowdata) =>
fetchingClient === rowdata.name
? "loading.." // Add your <Spinner />
: null,
},
{
field: "join",
sorting: false,
render: (rowdata) => (
<button
disabled={fetchingClient === rowdata.name}
onClick={(event) => fetchDataFromRemote(rowdata.name)}
>
Go fetch
</button>
),
},
];
const tableData = [
{
client: "client1",
name: "Jasnah",
year: "2019",
},
{
client: "client2",
name: "Dalinar",
year: "2018",
},
{
client: "client3",
name: "Kal",
year: "2019",
},
];
return (
<Fragment>
<MaterialTable
columns={tableColumns}
data={tableData}
title="Material Table - custom column "
options={{ search: false }}
/>
</Fragment>
);
}

AsyncSelect: how to set an initial value?

I am using AsyncSelect and need to change the value of the component based on outside logic.
For instance, I have this simple component:
import { colourOptions } from '../data';
const filterColors = (inputValue: string) => {
return colourOptions.filter(i =>
i.label.toLowerCase().includes(inputValue.toLowerCase())
);
};
const promiseOptions = inputValue =>
new Promise(resolve => {
setTimeout(() => {
resolve(filterColors(inputValue));
}, 1000);
});
export default class WithPromises extends Component {
render() {
return (
<AsyncSelect cacheOptions defaultOptions loadOptions={promiseOptions} />
);
}
}
Is there a way to set the initial value of it? I thought of using props but I couldn't figure out how execute onChange event as this would load the options array and set label and value.
Try adding a value like this:
<AsyncSelect
cacheOptions
defaultOptions
value={{ label: 'yellow', value: 2 }}
loadOptions={promiseOptions} />
it worked for me.
When changing the value from the menu options and selected item not change or changed happened based on outside logic then just use the state in value={yourState} to set the initial & updated values of AsyncSelect. Selected contain object like value={value:'', label:''}
const formFields = {
name: '',
foo:'',
bar:''
}
const [inputs, setInputs] = useState(formFields);
inputs is my state which i used to set the fields values
value={inputs.name ? { label: inputs.name } : { label: 'Search customer...' }}
I used only label:'Search customer...' to make it look like place holder.
<AsyncSelect
defaultOptions
value={inputs.name ? { label: inputs.name } : { label: 'Search customer...' }}
cacheOptions
onChange={(e) => handleCustomerSelect(e)}
loadOptions={customerPromiseOptions}
/>
here is my onChange which is called when item is select from dropdown menu
function handleCustomerSelect(selectedOption) {
const { value } = selectedOption;
setInputs({ ...inputs, name:value });
}
You can set your initial value from options as well like this