Issue
i am trying to create a search form using React typescript props event.I have acheived half of it but now stuck on an checkbox multiSelector where i have no idea how we can implement it.i have googled a lot but got nothing in return.
here is my code.
I am using common typescript props event onChange for setting all the values inside my search Api Object.
can anyone help me out with code or docs how we can acheive multiSelector checkbox for React Typescript props event.
1.here is my search for structure=>
enter code here
let columns = useMemo(
() => [
{
Header: "Name", accessor: "username",
Cell: (props: any) => {
if (authoritiesList.includes("USR-U")) {
let path = "/users/" + props.value;
return createClickableLink(path, props.value);
} else {
return <>
<span>{props.row.original.username}</span>
</>
}
},
FilterOptions: {
FilterInput:
<input type="text" placeholder="Username..." />,
overrideFilterLabel: "Username",
overrideFilterAccessor: "username"
}
},
{
Header: "Role(s)", accessor: "roles", disableSortBy: true,
Cell: (props: any) => {
return <>
{props.row.original.roles.map((role: any) => {
return (
<div>
<span>{role}</span><br/>
</div>)
})}
</>
},
FilterOptions: {
FilterSelect:
roleData.items.map((curRole:any)=>{
return (
<input type="checkbox value=
{curRole.name} />
)
})} ,
overrideFilterLabel: "Roles",
overrideFilterAccessor: "roles"
}
},
},
], [customerData,roleData]
)
enter code here
const selector = (state: any) => state.users;
return (
<div className="m-0 p-0 ">
<section id="content-wrapper">
<div className="row">
<div className="col-lg-12 ml-auto">
<Breadcrumb crumbs={crumbs}/>
<div className="table_data mt-2">
{createSearchButton()}
{authoritiesList.includes("USR-C") && createAddButton("/users/create", "Add User")}
<DataTable columns={columns}
fetchAction={userActions.getAllData as Dispatch<Action>}
exportAction={userActions.exportData as Dispatch<Action>}
selector={selector}/>
</div>
</div>
</div>
</section>
</div>
);
}
I want to handle multi selected checkbox event for this form in
Typescript. all forms input tags are working currently but multiselected checkbox is not working for brining output to the query object.
here is my typescript code.
for (let column of tableColumns) {
if (!column.FilterOptions) {
column.FilterOptions = {};
}
if (column.FilterOptions?.FilterSelect) {
column.FilterOptions.FilterSelect.props.onKeyPress = (event: KeyboardEvent) => {
event.key === 'Enter' && setApplyFilter(true);
}
column.FilterOptions.FilterSelect.props.onChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
updateFilterQuerySelect(column, filterQuery, setFilterQuery, event);
}
}
if (column.FilterOptions?.FilterInput) {
column.FilterOptions.FilterInput.props.onKeyPress = (event: KeyboardEvent) => {
event.key === 'Enter' && setApplyFilter(true);
}
column.FilterOptions.FilterInput.props.onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
updateFilterQuery(column, filterQuery, setFilterQuery, event);
}
}
}
here is function updateFilterQuery
const updateFilterQuery = (column: DataTableColumn, filterQuery: any, setFilterQuery: Function, event: React.ChangeEvent) => {
let tempQuery: any = {...filterQuery};
let key: string = column.FilterOptions?.overrideFilterAccessor || column.accessor;
let value: any = event.target.value;
if (event.target.value == "on" && event.target.checked != undefined) {
value = event.target.checked;
}
if (event.target.value == undefined) {
delete tempQuery[key];
} else {
key === 'phone' ? tempQuery[key] = getUnformattedPhoneNumber(value)
:
tempQuery[key] = value;
}
setFilterQuery(tempQuery);
}
It is a search form and similary it is working same as for other forms as well th eonly part missing in this form is now multiselector which is not working.
Solution
You have to separate selection state into a custom hook. A state is an array of selected items.
hooks.ts
import React, { useState } from "react";
export const useMultiselect = (initialValue: string[]) => {
const [selected, setSelected] = useState<string[]>(initialValue);
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
const index = selected.indexOf(value);
if (index > -1) {
setSelected([...selected.slice(0, index), ...selected.slice(index + 1)]);
} else {
setSelected([...selected, ...[value]]);
}
};
const isSelected = (value: string) => {
return selected.includes(value);
};
return { selected, isSelected, onChange };
};
App.tsx
import { useMultiselect } from "./hooks";
const data = ["Apple", "Orange", "Banana", "Pear", "Peach"];
export default function App() {
const { selected, isSelected, onChange } = useMultiselect([]);
return (
<div>
<div>Select your favorite fruites!</div>
<ul style={{ listStyleType: "none" }}>
{data.map((value) => (
<li key={value}>
<input
id={value}
type="checkbox"
value={value}
checked={isSelected(value)}
onChange={onChange}
/>
<label htmlFor={value}>{value}</label>
</li>
))}
</ul>
<div>Selected: {selected.join()}</div>
</div>
);
}
Answered By – Watanabe.N
Answer Checked By – Mildred Charles (BugsFixing Admin)