Material ui v1 autocomplete - how to style it/ pass props to it? - reactjs

Looking forward for any hint how to style new material ui v1 autocomplete or how to pass props to it.
Here's a codesandbox code (working example):
https://codesandbox.io/s/xrzq940854
In my particular case - I would like to style the label (which goes up after entering some value into input) and that horizontal line (underline under the input value).
Thank u for any help. (dropping code also in the snippet)
P.S. I got also a question how to pass props to the styles function. If anyone knows, please let me know :)
import React from 'react';
import PropTypes from 'prop-types';
import Autosuggest from 'react-autosuggest';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
import TextField from 'material-ui/TextField';
import Paper from 'material-ui/Paper';
import { MenuItem } from 'material-ui/Menu';
import { withStyles } from 'material-ui/styles';
const suggestions = [
{ label: 'Afghanistan' },
{ label: 'Aland Islands' },
{ label: 'Albania' },
{ label: 'Algeria' },
{ label: 'American Samoa' },
{ label: 'Andorra' },
{ label: 'Angola' },
{ label: 'Anguilla' },
{ label: 'Antarctica' },
{ label: 'Antigua and Barbuda' },
{ label: 'Argentina' },
{ label: 'Armenia' },
{ label: 'Aruba' },
{ label: 'Australia' },
{ label: 'Austria' },
{ label: 'Azerbaijan' },
{ label: 'Bahamas' },
{ label: 'Bahrain' },
{ label: 'Bangladesh' },
{ label: 'Barbados' },
{ label: 'Belarus' },
{ label: 'Belgium' },
{ label: 'Belize' },
{ label: 'Benin' },
{ label: 'Bermuda' },
{ label: 'Bhutan' },
{ label: 'Bolivia, Plurinational State of' },
{ label: 'Bonaire, Sint Eustatius and Saba' },
{ label: 'Bosnia and Herzegovina' },
{ label: 'Botswana' },
{ label: 'Bouvet Island' },
{ label: 'Brazil' },
{ label: 'British Indian Ocean Territory' },
{ label: 'Brunei Darussalam' },
];
function renderInput(inputProps) {
const { classes, autoFocus, value, ref, ...other } = inputProps;
return (
<TextField
autoFocus={autoFocus}
className={classes.textField}
value={value}
inputRef={ref}
label="Country"
InputProps={{
classes: {
input: classes.input,
},
...other,
}}
/>
);
}
function renderSuggestion(suggestion, { query, isHighlighted }) {
const matches = match(suggestion.label, query);
const parts = parse(suggestion.label, matches);
return (
<MenuItem selected={isHighlighted} component="div">
<div>
{parts.map((part, index) => {
return part.highlight ? (
<span key={String(index)} style={{ fontWeight: 300 }}>
{part.text}
</span>
) : (
<strong key={String(index)} style={{ fontWeight: 500 }}>
{part.text}
</strong>
);
})}
</div>
</MenuItem>
);
}
function renderSuggestionsContainer(options) {
const { containerProps, children } = options;
return (
<Paper {...containerProps} square>
{children}
</Paper>
);
}
function getSuggestionValue(suggestion) {
return suggestion.label;
}
function getSuggestions(value) {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
let count = 0;
return inputLength === 0
? []
: suggestions.filter(suggestion => {
const keep =
count < 5 && suggestion.label.toLowerCase().slice(0, inputLength) === inputValue;
if (keep) {
count += 1;
}
return keep;
});
}
const styles = theme => ({
container: {
flexGrow: 1,
position: 'relative',
height: 200,
},
suggestionsContainerOpen: {
position: 'absolute',
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit * 3,
left: 0,
right: 0,
},
suggestion: {
display: 'block',
},
suggestionsList: {
margin: 0,
padding: 0,
listStyleType: 'none',
},
textField: {
width: '100%',
},
label: {
color: 'yellow',
}
});
class IntegrationAutosuggest extends React.Component {
state = {
value: '',
suggestions: [],
};
handleSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value),
});
};
handleSuggestionsClearRequested = () => {
this.setState({
suggestions: [],
});
};
handleChange = (event, { newValue }) => {
this.setState({
value: newValue,
});
};
render() {
const { classes } = this.props;
return (
<Autosuggest
theme={{
container: classes.container,
suggestionsContainerOpen: classes.suggestionsContainerOpen,
suggestionsList: classes.suggestionsList,
suggestion: classes.suggestion,
}}
renderInputComponent={renderInput}
suggestions={this.state.suggestions}
onSuggestionsFetchRequested={this.handleSuggestionsFetchRequested}
onSuggestionsClearRequested={this.handleSuggestionsClearRequested}
renderSuggestionsContainer={renderSuggestionsContainer}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={{
autoFocus: true,
classes,
placeholder: 'Search a country (start with a)',
value: this.state.value,
onChange: this.handleChange,
}}
/>
);
}
}
IntegrationAutosuggest.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(IntegrationAutosuggest);

Material-UI v1 uses React-autosuggest module.
Check the below link
https://github.com/moroshko/react-autosuggest/blob/master/src/Autosuggest.js

Related

Type is not assignable to type 'IntrinsicAttributes & GridProps'

I'm new to frontend development with React/Redux/Typescript. I'm trying to make the components work. I want to use DataGrid from #mui/material/styles. https://mui.com/x/react-data-grid/.
I have tried searching online but I cannot figure out why I have this error.
My code:
import {
FilteringState,
IntegratedFiltering,
IntegratedPaging,
IntegratedSorting,
PagingState,
Row,
RowDetailState,
SearchState,
SelectionState,
SortingState,
} from "#devexpress/dx-react-grid";
import {
ColumnChooser,
Grid,
PagingPanel,
SearchPanel,
Table,
TableColumnResizing,
TableColumnVisibility,
TableFilterRow,
TableHeaderRow,
Toolbar,
} from "#devexpress/dx-react-grid-material-ui";
import { Card } from "#mui/material";
import { JiraDefect } from "api/classes/JiraDefect";
import { ReactText, useMemo, useState } from "react";
export default function RSADefectsTable(props: {
defects: JiraDefect[];
epicNames: { [key: string]: string };
fixVersions: string[];
}) {
const { defects } = props;
const [selection, setSelection] = useState<ReactText[]>([]);
const [search, setSearch] = useState<string>();
const [defect, setDefect] = useState<string>();
const [open, setOpen] = useState(false);
useMemo(() => {
if (defect) setOpen(true);
}, [defect]);
const [defaultColumnWidths] = useState([
{ columnName: "key", width: 125 },
{ columnName: "created", width: 125 },
{ columnName: "name", width: 500 },
{ columnName: "priority", width: 100 },
{ columnName: "severity", width: 100 },
{ columnName: "status", width: 200 },
{ columnName: "fixVersion", width: 125 },
{ columnName: "components", width: 125 },
{ columnName: "epicLink", width: 175 },
]);
const columns = [
{ name: "key", title: "Key" },
{ name: "created", title: "Created" },
{ name: "name", title: "Headline" },
{ name: "priority", title: "Priority" },
{ name: "severity", title: "Severity" },
{ name: "fixVersion", title: "Fix Version" },
{ name: "status", title: "Status" },
{ name: "components", title: "Component" },
{ name: "epicLink", title: "Epic Name" },
];
const cellValue = (row: JiraDefect, column: string) => {
if (column === "status") return (row[column as keyof JiraDefect] as string).replace(/_/g, " ");
if (column === "priority") return (row[column as keyof JiraDefect] as string).replace(/..- /g, "");
if (column === "created") return row.created.toISOString().slice(0, 10);
if (column === "epicLink" && row.epicLink) return props.epicNames[row.epicLink];
return row[column as keyof JiraDefect];
};
const TableRow = ({ row, ...restProps }: { row: Row }) => (
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
<Table.Row
{...restProps}
onClick={() => {
setDefect(row["key"]);
window.open("https://jira.tooling.intactfc.cloud/browse/" + row["key"]);
}}
style={{ cursor: "pointer" }}
/>
);
const filteredDefects = defects.filter((val) => props.fixVersions.includes(val.fixVersion[0]));
return (
<>
<Card style={{ borderRadius: 10 }}>
<Grid columns={columns} rows={filteredDefects} getCellValue={cellValue}>
<PagingState defaultCurrentPage={0} pageSize={20} />
<SortingState defaultSorting={[{ columnName: "key", direction: "desc" }]} columnSortingEnabled />
<IntegratedSorting />
<SearchState onValueChange={setSearch} value={search} />
<FilteringState />
<RowDetailState />
<SelectionState selection={selection} onSelectionChange={setSelection} />
<IntegratedFiltering />
<IntegratedPaging />
<Toolbar />
<SearchPanel />
<Table rowComponent={TableRow} />
<TableColumnResizing defaultColumnWidths={defaultColumnWidths} />
<TableHeaderRow showSortingControls />
<TableColumnVisibility />
<ColumnChooser />
<TableFilterRow />
<PagingPanel />
</Grid>
</Card>
</>
);
}
Error:
[![enter image description here][1]][1]
Any help will be appreciated.

Material-UI-Search Bar value not clearing

I am using the #material-ui-searchbar to filter data. I'm using the same container for multiple different pages to display the info. When ever I switch between pages (and thus the data) the whole container reloads to display the new data and new {subType}... however, despite me changing the value of {searched} using setSearched("")(verified that it does in fact change from the debugger), the old search value from the previous page/state remains in the search bar even though the search is inactive. Why won't the search bar value update with the change of state? Doesn't make intuitive sense. Here is the code for my container:
import SearchBar from 'material-ui-search-bar';
const facilityGridConfig = {
hospitals: {
columns: [
{ name: 'name', title: 'Name' },
{ name: 'address1', title: 'Address' },
{ name: 'city', title: 'City' },
{ name: 'state', title: 'State' },
{ name: 'zipcode', title: 'Zip' },
{ name: 'phoneNumber', title: 'Phone' },
{ name: 'userTotal', title: 'Therapists', link: '/users/therapists' },
{ name: 'endUserTotal', title: 'Patients', link: '/users/patients' },
]
},
clinics: {
columns: [
{ name: 'name', title: 'Name' },
{ name: 'address1', title: 'Address' },
{ name: 'city', title: 'City' },
{ name: 'state', title: 'State' },
{ name: 'zipcode', title: 'Zip' },
{ name: 'phoneNumber', title: 'Phone' },
{ name: 'userTotal', title: 'Therapists', link: '/users/therapists' },
{ name: 'endUserTotal', title: 'Patients', link: '/users/patients' },
]
},
staff: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: 'facility', title: 'Facility' },
{ name: 'logins', title: 'Logins', width: 90 },
{ name: 'enrollmentStatus', title: 'Status', width: 90 },
{ name: 'email', title: 'Email' },
{ name: 'phoneNumber', title: 'Phone' }
]
},
therapists: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: 'facility', title: 'Facility' },
{ name: 'logins', title: 'Logins', width: 90 },
{ name: 'enrollmentStatus', title: 'Status', width: 90 },
{ name: 'email', title: 'Email' },
{ name: 'phoneNumber', title: 'Phone' },
{ name: 'endUserTotal', title: 'Patients' },
]
},
patients: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: 'facility', title: 'Facility' },
{ name: 'email', title: 'Email' },
{ name: "sessionsInPastWeek", title: "Sessions Last 7 Days"},
]
}
};
const facilityGridConfigSmall = {
hospitals: {
columns: [
{ name: 'name', title: 'Name' },
{ name: 'userTotal', title: 'Therapists', link: '/users/therapists' },
{ name: 'endUserTotal', title: 'Patients', link: '/users/patients' },
]
},
clinics: {
columns: [
{ name: 'name', title: 'Name' },
{ name: 'userTotal', title: 'Therapists', link: '/users/therapists' },
{ name: 'endUserTotal', title: 'Patients', link: '/users/patients' },
]
},
staff: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: 'logins', title: 'Logins' }
]
},
therapists: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: 'logins', title: 'Logins' },
{ name: 'endUserTotal', title: 'Patients' },
]
},
patients: {
columns: [
{ name: 'firstName', title: 'First Name' },
{ name: 'lastName', title: 'Last Name' },
{ name: "sessionsInPastWeek", title: "Sessions Last 7 Days"},
]
}
};
const useStyles = makeStyles((theme: Theme) => ({
root: {
position: 'relative',
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
height: '100%',
},
container: {
position: 'relative',
height: '100%',
},
breadcrumb: {
fontFamily: "Open Sans",
height: '28px',
},
content: {
position: 'relative',
height: 'calc(100% - 28px)',
},
gridHeaderEdit: {
textAlign: 'center!important' as any,
},
menuIcon: {
marginRight: theme.spacing(1)
},
}));
const FacilitiesGridContainer = (props: any) => {
const {
type,
subType,
uid,
} = props;
const mountedRef = useRef(true);
const classes = useStyles();
const dispatch = useDispatch();
const targetType = uid ? (
subType === Navigations.facilities.hospitals ? Navigations.facilities.clinics :
subType === Navigations.facilities.clinics ? Navigations.users.therapists : Navigations.users.patients
) : subType
const userProfile = useSelector(state => _get(state, ['user', 'profile']) || {}, shallowEqual);
const activeHospital = useSelector(state => _get(state, ['facilities', 'activeHospital']) || null, shallowEqual);
const activeClinic = useSelector(state => _get(state, ['facilities', 'activeClinic']) || null, shallowEqual);
const data = useSelector(state => _get(state, ['facilities', targetType]) || [], shallowEqual);
const loading = useSelector(state => _get(state, ['facilities', 'loading']) || false, shallowEqual);
const [fdata, setfData] = useState(data.data);
const [ openDeleteModal, setopenDeleteModal ] = useState(false);
const [ openInviteModal, setOpenInviteModal ] = useState(false);
const [ facilitiesInEdit, setFacilitiesInEdit ] = useState([] as any);
const [ sort, setSort ] = useState([] as any); //[{ field: 'name', dir: 'asc' }]
const [ visibleAddButton, setVisibleAddButton ] = useState(true);
const [ singleSubType, setSingleSubType ] = useState('');
const [ windowTitle, setWindowTitle ] = useState('');
const [ modalUserName, setModalUserName ] = useState('');
const [ visibleQRModal, setVisibleQRModal ] = useState(true);
const [ openQRModal, setOpenQRModal ] = useState(false);
const [ qrString, setQRString ] = useState('');
const [ qrFullName, setQRfullName ] = useState('');
const gridConfig = _get(facilityGridConfig, [targetType]) || {};
const gridConfigSmall = _get(facilityGridConfigSmall, [targetType]) || {};
const [searched, setSearched] = useState("");
const requestSearch = (searchedVal: string) => {
const filteredData = data.data.filter((row:any) => {
if (subType === "therapists" || subType === "patients" || subType === "staff"){
return (row['firstName'].toLowerCase().includes(searchedVal.toLowerCase()) || row['lastName'].toLowerCase().includes(searchedVal.toLowerCase()));
}
else {
return (row['name'].toLowerCase().includes(searchedVal.toLowerCase()));
}
});
setfData(filteredData);
};
const cancelSearch = () => {
setSearched("");
requestSearch(searched);
};
useEffect(() => {
setSearched("");
return () => {
mountedRef.current = false;
}
}, []);
useEffect(() => {setfData(data.data)}, [data.data] )
useEffect(() => {
setSearched("");
if (subType === Navigations.facilities.hospitals) {
if (uid) {
setSingleSubType('clinic');
} else {
setSingleSubType('hospital');
}
}
else if (subType === Navigations.facilities.clinics) {
if (uid) {
setSingleSubType('therapist');
} else {
setSingleSubType('clinic');
}
}
else if (subType === Navigations.users.therapists) {
if (uid) {
setSingleSubType('patient');
} else {
setSingleSubType('therapist');
}
}
else if (subType === Navigations.users.staff) {
setSingleSubType('staff');
}
else
setSingleSubType('patient');
return () => {
}
}, [subType, uid]);
useEffect(() => {
console.log('call to api here...')
dispatch({
type: FacilityActionType.GetFacilities,
payload: {
type: type,
subType: subType,
targetType: targetType,
facilityUid: targetType === 'therapists' ? (uid || null) : (_get(activeClinic, 'uid') || null),
parentFacilityUid: uid ? null : (_get(activeHospital, 'uid') || null),
parentUid: uid || null,
skip: 0,
take: 0
}
});
if (!userProfile)
setVisibleAddButton(false);
if (subType === 'hospitals') {
if ([UserRoles.SYSTEMADMIN].indexOf(userProfile.role) >= 0 && !!uid) {
setVisibleAddButton(true);
} else if ([UserRoles.SUPERUSER].indexOf(userProfile.role) < 0) {
setVisibleAddButton(false);
} else {
setVisibleAddButton(true);
}
}
else if (subType === 'clinics') {
if ([UserRoles.FACILITYADMIN].indexOf(userProfile.role) >= 0 && !!uid) {
setVisibleAddButton(true);
} else if ([UserRoles.SUPERUSER, UserRoles.SYSTEMADMIN, UserRoles.FACILITYADMIN].indexOf(userProfile.role) < 0) {
setVisibleAddButton(false);
} else {
setVisibleAddButton(true);
}
} else if (subType === 'therapists') {
if ([UserRoles.SUPERUSER, UserRoles.SYSTEMADMIN, UserRoles.FACILITYADMIN].indexOf(userProfile.role) < 0) {
setVisibleAddButton(false);
} else {
setVisibleAddButton(true);
}
} else if (subType === 'patients') {
if ([UserRoles.SUPERUSER, UserRoles.SYSTEMADMIN, UserRoles.FACILITYADMIN, UserRoles.USER].indexOf(userProfile.role) < 0) {
setVisibleAddButton(false);
} else {
setVisibleAddButton(true);
}
}
setWindowTitle("Augment Therapy: "+subType.charAt(0).toUpperCase() + subType.slice(1));
setSearched("");
return () => {
};
}, [userProfile, subType, uid, dispatch, type, targetType, activeClinic, activeHospital])
useEffect(() => {
setSearched("");
if (data) {
if (subType === Navigations.users.therapists) {
for (let rec of data.data) {
if (!rec['enrollmentStatus']) {
rec.enrollmentStatus = '--'
}
}
}
}
}, [subType,data]);
const setActiveFacility = (dataItem: any) => {
const payload: any = getActiveFacilityPayload(subType, uid);
if (dataItem.facilityType === FacilityType.Hospital) {
payload.activeHospital = dataItem;
} else if (dataItem.facilityType === FacilityType.Clinic) {
payload.activeClinic = dataItem;
} else if (subType === 'clinics' && !!uid) {
payload.activeTherapist = dataItem;
} else if (subType === 'staff' && !uid) {
payload.activeStaff = dataItem;
} else if (subType === 'therapists' && !uid) {
payload.activeTherapist = dataItem;
} else {
payload.activePatient = dataItem;
}
dispatch({type: FacilityActionType.SetActiveFacility, payload: payload});
}
const handleRowClick = (e: any) => {
setActiveFacility(e.dataItem);
if (e.dataItem) {
if (e.dataItem.facilityType === FacilityType.Hospital) {
navigate(`${Navigations.facilities.root}/${Navigations.facilities.hospitals}/${e.dataItem.uid}`, false);
} else if (e.dataItem.facilityType === FacilityType.Clinic) {
navigate(`${Navigations.facilities.root}/${Navigations.facilities.clinics}/${e.dataItem.uid}`, false);
} else if (subType === 'clinics') {
if (!uid) {
navigate(`${Navigations.facilities.root}/${Navigations.facilities.clinics}/${_get(e.dataItem, 'uid')}`, false);
} else { // it's therapist
navigate(`${Navigations.users.root}/${Navigations.users.therapists}/${_get(e.dataItem, 'uid')}`, false);
}
} else if (subType === 'therapists') {
if (!uid) {
navigate(`${Navigations.users.root}/${Navigations.users.therapists}/${_get(e.dataItem, 'uid')}`, false);
} else { // it's therapist
navigate(`${Navigations.users.root}/${Navigations.users.patients}/${_get(e.dataItem, 'uid')}`, false);
}
} else if (subType === 'patients') {
navigate(`${Navigations.users.root}/${Navigations.users.patients}/${_get(e.dataItem, 'uid')}`, false);
}
}
}
const handleLink = (dataItem: any, fieldName: string) => {
setActiveFacility(dataItem);
if (fieldName === 'userTotal') {
navigate(`${Navigations.users.root}/${Navigations.users.therapists}`, false);
} else if (fieldName === 'endUserTotal') {
navigate(`${Navigations.users.root}/${Navigations.users.patients}`, false);
}
}
const handleEdit = (dataItem: any) => {
let newType = Navigations.facilities.root;
if (targetType === Navigations.users.staff || targetType === Navigations.users.therapists || targetType === Navigations.users.patients) {
newType = Navigations.users.root;
}
if (dataItem) {
setActiveFacility(dataItem);
navigate(`${newType}/${targetType}/edit`, false, {uid: dataItem.uid});
} else {
navigate(`${newType}/${targetType}/new`);
}
}
const handleDelete = (dataItem: any) => {
setFacilitiesInEdit([...facilitiesInEdit, dataItem]);
setModalName(dataItem);
setopenDeleteModal(true);
}
const handleDeleteOk = () => {
dispatch({
type: FacilityActionType.DeleteFacilities,
payload: {
type: type,
subType: subType,
targetType: targetType,
body: facilitiesInEdit
}});
setopenDeleteModal(false);
}
const handleDeleteCancel = () => {
setFacilitiesInEdit([]);
setopenDeleteModal(false);
};
const handleInvite = (dataItem: any) => {
//setFacilitiesInEdit([...facilitiesInEdit, dataItem]);
setFacilitiesInEdit([dataItem]);
setModalName(dataItem);
setOpenInviteModal(true);
};
const handleInviteOk = () => {
dispatch({
type: FacilityActionType.PostUserSendInvite,
payload: {
body: facilitiesInEdit,
},
});
setOpenInviteModal(false);
};
const handleInviteCancel = () => {
setFacilitiesInEdit([]);
setOpenInviteModal(false);
};
const setModalName = (dataItem: any) => {
if (dataItem.firstName) {
setModalUserName(dataItem.firstName+' '+dataItem.lastName);
} else {
setModalUserName(dataItem.name);
}
return () => {
}
}
const closeQR = () => {
setOpenQRModal( false );
};
const handleQR = (dataItem: any) => {
setFacilitiesInEdit([...facilitiesInEdit, dataItem]);
setQRString(dataItem.qr);
if (dataItem.lastName) {
setQRfullName( dataItem.firstName + ' ' + dataItem.lastName.charAt(0) + '.' );
} else {
setQRfullName( dataItem.firstName );
}
setOpenQRModal(true);
};
return (
<Page
className={classes.root}
title={windowTitle}
>
<Container
maxWidth={false}
className={classes.container}
>
<Grid
container
direction='row'
style={{height: '100%'}}
>
<Grid
item
xs={12}
className={classes.breadcrumb}
>
<FacilitiesBreadCrumb
type={type}
subType={subType}
/>
</Grid>
<Grid
item
xs={12}
className={classes.content}
>
{
loading && (
<CircularIndeterminate/>
)
}
<Grid item xs={12} >
<StatsCards
type={subType}
uid={uid}
/>
</Grid>
<Hidden mdDown>
<DataGrid
style={{ height: '100%', overflow: 'auto', cursor:'pointer' }}
data={orderBy(fdata, sort)}
sortable={{
mode: 'multiple',
}}
sort={sort}
onSortChange={(e) => {
setSort(e.sort);
}}
onRowClick={(e: any) => handleRowClick(e)}
>
{
(visibleAddButton) && (
<GridToolbar>
<Grid container
style={{justifyContent: 'center', display: 'flex', alignItems: 'center', padding: 10}}>
<Grid item>
<SearchBar
value={searched}
onChange={(searchVal) => requestSearch(searchVal)}
onCancelSearch={() => cancelSearch()}
style={{
display: 'flex',
margin: '0 auto',
maxWidth: 800,
minWidth: 800,
paddingRight: 10
}}>
</SearchBar>
</Grid>
<Grid item>
<button
title="Add new"
className="k-button k-primary"
onClick={() => handleEdit(null)}
style={{
height: 50,
paddingLeft: 10
}}
>
Add New {singleSubType}
</button>
</Grid>
</Grid>
</GridToolbar>
)
}
{
(!(targetType==='hospitals' || targetType==='clinics')) && (
<GridColumn
title="Badge"
width="100"
headerClassName={classes.gridHeaderEdit}
cell={CellWithQR({userProfile: userProfile, type:"badge", handleAction: handleQR})}
/>
)
}
{
((targetType==='hospitals' || targetType==='clinics')) && (
<GridColumn
title=""
width="1"
headerClassName={classes.gridHeaderEdit}
cell={CellWithEdit({userProfile: userProfile, type:"empty", handleAction: handleInvite})}
/>
)
}
{
gridConfig.columns.map((c: any, index: number) => {
return (
<GridColumn key={`grid-${index}`}
field={c.name}
title={c.title}
cell={c.link ? CellWithLink({handleLink}) : undefined}
width= {c.width ? c.width : undefined}
/>
)
})
}
<GridColumn
title="Actions"
width="100"
headerClassName={classes.gridHeaderEdit}
cell={CellWithComboMenu({userProfile: userProfile, type:"edit", handleActionInvite: handleInvite, handleActionEdit: handleEdit, handleActionDelete: handleDelete})}
/>
</DataGrid>
</Hidden>
<Hidden lgUp>
<DataGrid
style={{ height: '100%', overflow: 'auto', cursor:'pointer' }}
data={orderBy(fdata, sort)}
sortable={{
mode: 'multiple',
}}
sort={sort}
onSortChange={(e) => {
setSort(e.sort);
}}
onRowClick={(e: any) => handleRowClick(e)}
>
{
(visibleAddButton) && (
<GridToolbar>
<Grid container
style={{justifyContent: 'center', display: 'flex', alignItems: 'center', padding: 10}}>
<Grid item>
<SearchBar
value={searched}
onChange={(searchVal) => requestSearch(searchVal)}
onCancelSearch={() => cancelSearch()}
style={{
display: 'flex',
margin: '0 auto',
maxWidth: 800,
paddingRight: 10
}}>
</SearchBar>
</Grid>
<Grid item>
<button
title="Add new"
className="k-button k-primary"
onClick={() => handleEdit(null)}
style={{
height: 50,
paddingLeft: 10
}}
>
Add New {singleSubType}
</button>
</Grid>
</Grid>
</GridToolbar>
)
}
{
(!(targetType==='hospitals' || targetType==='clinics')) && (
<GridColumn
title="Badge"
width="20"
headerClassName={classes.gridHeaderEdit}
cell={CellWithQR({userProfile: userProfile, type:"badge", handleAction: handleQR})}
/>
)
}
{
((targetType==='hospitals' || targetType==='clinics')) && (
<GridColumn
title=""
width="10"
headerClassName={classes.gridHeaderEdit}
cell={CellWithEdit({userProfile: userProfile, type:"empty", handleAction: handleInvite})}
/>
)
}
{
gridConfigSmall.columns.map((c: any, index: number) => {
return (
<GridColumn key={`grid-${index}`}
field={c.name}
title={c.title}
cell={c.link ? CellWithLink({handleLink}) : undefined}
minResizableWidth = {c.name.toLowerCase().includes("name")? 20 : 10}
/>
)
})
}
<GridColumn
title="Actions"
width="100"
headerClassName={classes.gridHeaderEdit}
cell={CellWithComboMenu({userProfile: userProfile, type:"edit", handleActionInvite: handleInvite, handleActionEdit: handleEdit, handleActionDelete: handleDelete})}
/>
</DataGrid>
</Hidden>
<ConfirmModal
title="Confirm Deletion"
content={`Are you sure you want to delete the ${singleSubType} ( ${modalUserName} ) ?`}
open={openDeleteModal}
handleClose={handleDeleteCancel}
handleOk={handleDeleteOk}
handleCancel={handleDeleteCancel}
/>
<ConfirmModal
title="Confirm Invite"
content={`Send ${modalUserName} an invitation to connect?`}
open={openInviteModal}
handleClose={handleInviteCancel}
handleOk={handleInviteOk}
handleCancel={handleInviteCancel}
/>
{
(openQRModal) && (
<UserQRCode
id="qrCode"
qrCodeString={qrString}
size={256}
userfullname={qrFullName}
open={true}
handleClose={closeQR}
/>
)
}
</Grid>
</Grid>
</Container>
</Page>
);
}
export default FacilitiesGridContainer;```
Well, I'm new to reactjs, but I suggest to call setSearched in a useEffect hook if your filteredData get changed. So it'll be something like this :
useEffect(() => {
setSearched("");
}, [filteredData])
..despite me changing the value of {searched} using setSearched("")..
this because you call setSearched("") on compoenent mount using (useEffect) but you need this to be called every time your filteredData get updated

How to select all options in react select?

I am not able to implement select all option for react select.
Below is my code
Here I am using react-select with multi select option.
when I click on select all option it should select all options in the dropdown and save it in a state variable.
import React from "react";
import Select,{components} from 'react-select';
import '../App.css'
const options = [
{ value: '*', label: 'Select All' },
{ value: 'ocean', label: 'Ocean', color: '#00B8D9', isFixed: true },
{ value: 'blue', label: 'Blue', color: '#0052CC', isDisabled: true },
{ value: 'purple', label: 'Purple', color: '#5243AA' },
{ value: 'red', label: 'Red', color: '#FF5630', isFixed: true },
{ value: 'orange', label: 'Orange', color: '#FF8B00' },
{ value: 'yellow', label: 'Yellow', color: '#FFC400' },
{ value: 'green', label: 'Green', color: '#36B37E' },
{ value: 'forest', label: 'Forest', color: '#00875A' },
{ value: 'slate', label: 'Slate', color: '#253858' },
{ value: 'silver', label: 'Silver', color: '#666666' },
];
export default function ReactSelect() {
const [value,setValue]=React.useState([])
const handleChange = (val) => {
if(val && val.length && val[0].value==='*'){
let arr=options;
arr.splice(0,0);
setValue([...arr])
}
else{
setValue( [...val] );}
}
return (
<div id="select">
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen </p>
<Select
onChange={handleChange}
isMulti
name="colors"
options={options}
className="basic-multi-select"
classNamePrefix="select"
closeMenuOnSelect={false}
hideSelectedOptions={false}
components={{ ValueContainer }}
value={value}
/>
<button onClick={()=>console.log(value)}>CLick</button>
</div>
);
}
const ValueContainer = ({ children, ...props }) => {
let [values, input] = children;
if (Array.isArray(values)) {
const val = (i= Number) => values[i].props.children;
const { length } = values;
switch (length) {
case 1:
values = `${val(0)} `;
break;
default:
const otherCount = length - 1;
values = `${val(0)}+ ${otherCount} `;
break;
}
}
return (
<components.ValueContainer {...props}>
{values}
{input}
</components.ValueContainer>
);
};
I tried to implement with select all option but its not working. Is there any inbuilt facility for it or any other select library which has multi select option with select all facility.

React - Uncaught TypeError: Cannot read property 'toLowerCase' of undefined

After entering the color name in the input field, when I submit the form, an error occurs :
TypeError: Cannot read property 'toLowerCase' of undefined
(anonymous function)
C:/Users/HP/Documents/WDB/React/Practice/colors-app/src/NewPaletteForm.js:117
114 | //to check -> is 'palette name' unique
115 | ValidatorForm.addValidationRule("isPaletteNameUnique", value => {
116 | return palettes.every(
> 117 | ({ paletteName }) => paletteName.toLowerCase() !== value.toLowerCase()
118 | ^ );
119 | });
120 | })
App.js : (Class-based component)
class App extends Component {
constructor(props) {
super(props);
this.state = { palettes: seedColors };
this.findPalette = this.findPalette.bind(this);
this.savePalette = this.savePalette.bind(this);
}
savePalette(newPalette) {
this.setState({ palettes: [...this.state.palettes, newPalette] });
}
render() {
return (
<Switch>
<Route
exact
path='/palette/new'
render={(routeProps) =>
<NewPaletteForm
savePalette={this.savePalette}
palettes={this.state.palettes}
{...routeProps}
/>}
/>
NewPaletteForm.js : (Functional component and uses react hooks)
function NewPaletteForm(props) {
const classes = useStyles();
const [open, setOpen] = useState(false);
const [currentColor, setCurrentColor] = useState('teal');
const [colors, setColors] = useState([{ color: 'pink', name: 'pink' }]);
const [fields, setFields] = useState({
newColorName: '',
newPaletteName: ''
})
useEffect(() => {
ValidatorForm.addValidationRule('isColorNameUnique', (value) => {
return colors.every(
({ name }) => name.toLowerCase() !== value.toLowerCase()
);
});
ValidatorForm.addValidationRule('isColorUnique', (value) => {
return colors.every(
({ color }) => color !== currentColor
);
});
ValidatorForm.addValidationRule("isPaletteNameUnique", value => {
return props.palettes.every(
({ paletteName }) => paletteName.toLowerCase() !== value.toLowerCase()
);
});
})
function addNewColor() {
const newColor = {
color: currentColor,
name: fields.newColorName
}
setColors(oldColors => [...oldColors, newColor]);
setFields({ newColorName: '' });
};
function handleChange(evt) {
setFields({ ...fields, [evt.target.name]: evt.target.value });
}
function handleSubmit() {
let newName = fields.newPaletteName;
const newPalette = {
paletteName: newName,
id: newName.toLowerCase().replace(/ /g, '-'),
colors: colors
}
props.savePalette(newPalette);
props.history.push('/');
}
Validator form components for colors and palettes :
<ValidatorForm onSubmit={handleSubmit}>
<TextValidator
label='Palette Name'
value={fields.newPaletteName}
name='newPaletteName'
onChange={handleChange}
validators={['required', 'isPaletteNameUnique']}
errorMessages={['Enter Palette Name', 'Name already used']} />
<Button variant='contained' color='primary' type='submit'>
Save Palette
</Button>
</ValidatorForm>
<ValidatorForm onSubmit={addNewColor}>
<TextValidator
value={fields.newColorName}
name='newColorName'
onChange={handleChange}
validators={['required', 'isColorNameUnique', 'isColorUnique']}
errorMessages={['Enter a color name', 'Color name must be unique', 'Color already used!']}
/>
<Button
variant='contained'
type='submit'
color='primary'
style={{
backgroundColor: currentColor
}}
>
Add Color
</Button>
</ValidatorForm>
seedColors.js:
export default [
{
paletteName: "Material UI Colors",
id: "material-ui-colors",
emoji: "🎨",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
{ name: "purple", color: "#9C27B0" },
{ name: "deeppurple", color: "#673AB7" },
{ name: "indigo", color: "#3F51B5" },
{ name: "blue", color: "#2196F3" },
{ name: "lightblue", color: "#03A9F4" },
{ name: "cyan", color: "#00BCD4" },
{ name: "teal", color: "#009688" },
{ name: "green", color: "#4CAF50" },
{ name: "lightgreen", color: "#8BC34A" },
{ name: "lime", color: "#CDDC39" },
{ name: "yellow", color: "#FFEB3B" },
{ name: "amber", color: "#FFC107" },
{ name: "orange", color: "#FF9800" },
{ name: "deeporange", color: "#FF5722" },
{ name: "brown", color: "#795548" },
{ name: "grey", color: "#9E9E9E" },
{ name: "bluegrey", color: "#607D8B" }
]
},
{
paletteName: "Flat UI Colors v1",
id: "flat-ui-colors-v1",
emoji: "🤙",
colors: [
{ name: "Turquoise", color: "#1abc9c" },
{ name: "Emerald", color: "#2ecc71" },
{ name: "PeterRiver", color: "#3498db" },
{ name: "Amethyst", color: "#9b59b6" },
{ name: "WetAsphalt", color: "#34495e" },
{ name: "GreenSea", color: "#16a085" },
{ name: "Nephritis", color: "#27ae60" },
{ name: "BelizeHole", color: "#2980b9" },
{ name: "Wisteria", color: "#8e44ad" },
{ name: "MidnightBlue", color: "#2c3e50" },
{ name: "SunFlower", color: "#f1c40f" },
{ name: "Carrot", color: "#e67e22" },
{ name: "Alizarin", color: "#e74c3c" },
{ name: "Clouds", color: "#ecf0f1" },
{ name: "Concrete", color: "#95a5a6" },
{ name: "Orange", color: "#f39c12" },
{ name: "Pumpkin", color: "#d35400" },
{ name: "Pomegranate", color: "#c0392b" },
{ name: "Silver", color: "#bdc3c7" },
{ name: "Asbestos", color: "#7f8c8d" }
]
}
]
What you can do is check to see if the value exists before calling toLowerCase.
Try using ?., like this
Instead of using value.toLowerCase() use value?.toLowerCase().
That way if the value is undefined or null, it won't call toLowerCase()
If paletteName is the one failing you can use paletteName?.toLowerCase()
If you want to go completely safe you do
paletteName?.toLowerCase() !== value?.toLowerCase()

react-select how to edit created entries

I'm using the Select.AsyncCreatable:
<Select.AsyncCreatable
clearableValue={true}
multi={true}
scrollMenuIntoView={true}
name="field-name"
value={values}
loadOptions={this.getOptions}
onChange={value => {
this.handleOnChange(value...)
}}
placeholder={this.defaultPlaceholder}
/>
How can I edit options I did create. I can remove created options and reenter them, but is there an option to edit selected values? It would be more comfortable.
Not sure how to do it with react-select, but I think what you are looking for is editable-creatable-multiselect
Here's a demo:
I really can't find any solution for this so i just modified what i found online and made it editable:
https://codesandbox.io/s/n4nqrjw564
hope it helps.
editing to add the code:
import React from "react";
const initialValues = [
{ label: "Test1", value: "Test1" },
{ label: "Test2", value: "Test2" },
{ label: "Test3", value: "Test3" }
];
const createOption = label => ({
label,
value: label
});
export default class TagsInput extends React.Component {
constructor(props) {
super(props);
this.state = {
//value: [],
value: initialValues,
focused: false,
inputValue: ""
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleInputKeyDown = this.handleInputKeyDown.bind(this);
this.handleEditItem = this.handleEditItem.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
render() {
const styles = {
container: {
border: "1px solid #ddd",
padding: "5px",
borderRadius: "5px"
},
items: {
display: "inline-block",
padding: "2px",
border: "1px solid black",
fontFamily: "Helvetica, sans-serif",
borderRadius: "5px",
marginRight: "5px",
cursor: "pointer"
},
input: {
outline: "none",
border: "none",
fontSize: "14px",
fontFamily: "Helvetica, sans-serif"
}
};
return (
<label>
<ul style={styles.container}>
{this.state.value.map((item, i) => (
<li key={i} style={styles.items} onClick={this.handleEditItem(i)}>
{item.label}
</li>
))}
<input
style={styles.input}
value={this.state.inputValue}
onChange={this.handleInputChange}
onKeyDown={this.handleInputKeyDown}
onBlur={this.handleBlur}
/>
</ul>
</label>
);
}
handleBlur(evt) {
const { value } = evt.target;
if (value !== "") {
this.setState(state => ({
value: [...state.value, createOption(value)],
inputValue: ""
}));
}
console.log(this.state.value);
}
handleInputChange(evt) {
this.setState({ inputValue: evt.target.value });
}
handleInputKeyDown(evt) {
if (evt.keyCode === 13) {
const { value } = evt.target;
if (value !== "") {
this.setState(state => ({
value: [...state.value, createOption(value)],
inputValue: ""
}));
}
}
if (evt.keyCode === 9) {
const { value } = evt.target;
if (value !== "") {
this.setState(state => ({
value: [...state.value, createOption(value)],
inputValue: ""
}));
}
}
if (
this.state.value.length &&
evt.keyCode === 8 &&
!this.state.inputValue.length
) {
this.setState(state => ({
value: state.value.slice(0, state.value.length - 1)
}));
}
console.log(this.state.value);
}
handleEditItem(index) {
return () => {
let it = this.state.value.filter((item, i) => i === index);
console.log(it);
this.setState(state => ({
value: state.value.filter((item, i) => i !== index),
inputValue: it[0].label
}));
//need to change to text box or open a new textbox
};
}
}

Resources