display doesn't show an element in MaterialUi in breakpoints - material-ui

I have a box component. I need to hide it if props are false and show if one of them is true. But when props are true, it is hidden. But when I switch to another component and return to those with boxes, it becomes visible.
<Box
component={Grid}
display={{
xs: error || activity ? "block" : "none",
sm: error || activity ? "block" : "none",
md: "block",
}}
>
<Component/>
</Box>

It would be easier to just use a condition in your return to display it or not.
function theBox(props){
return (
{ props.display &&
<Box
component={Grid}
display={{
xs: error || activity ? "block" : "none",
sm: error || activity ? "block" : "none",
md: "block",
}}
>
<Component/>
</Box>
}
);
}

Related

Formik - arrayfields -- validation handling

I am working with formik/material ui -- and yup validation. I am struggling to get validation showing/working on field arrays
my schema and validation looks like this currently for each field.
"fields": [
{
"type": "date",
"label": "Start Date",
"name": "startDate",
"validation": yup.date().default(function () { return new Date() }).required("date is required").nullable().typeError(''),
"minDate": moment().add(1, 'weeks'),
"maxDate": moment().add(8, 'weeks'),
"disablePast": true,
"disableFuture": false,
//"disabled": true
},
{
"type": "date",
"label": "End Date",
"name": "endDate",
"validation": yup.date().default(function () { return new Date() }).required("date is required").nullable().typeError(''),
"minDate": moment().add(1, 'weeks'),
"maxDate": moment().add(8, 'weeks'),
"disablePast": true,
"disableFuture": false,
//"disabled": true
}
]
I've seen on formik - they have some validation like this - but how do I apply it my code base for dates?
https://formik.org/docs/api/fieldarray
const schema = Yup.object().shape({
friends: Yup.array()
.of(
Yup.object().shape({
name: Yup.string().min(4, 'too short').required('Required'), // these constraints take precedence
salary: Yup.string().min(3, 'cmon').required('Required'), // these constraints take precedence
})
)
.required('Must have friends') // these constraints are shown if and only if inner constraints are satisfied
.min(3, 'Minimum of 3 friends'),
});
my fieldarray looks like this -- and I believe errors should appear under the field group -- the fields outer border goes red -- but it doesn't seem to work for when I null the date - like is required date working?
<>
<FieldArray
name={item.name}
onChange={event => {
console.log("event field array change", event)
}}
>
{({ insert, remove, push }) => (
<div className="field field-array">
<div className="row" key={0}>
{item.fields.map((ch, inx) => (
<span key={"x"+inx}>
<div className="col-x">
<Field
name={`${item.name}.${ch.name}`}
>
{({
field, // { name, value, onChange, onBlur }
form,
meta,
}) => (
<>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label={ch.label}
disablePast={ch.disablePast}
disableFuture={ch.disableFuture}
minDate={moment(ch.minDate)}
maxDate={moment(ch.maxDate)}
value={field.value? moment(field.value).format('YYYY-MM-DD'): moment().format('YYYY-MM-DD')}
{...field}
onChange={(value) => {
form.setFieldValue(field.name, value);
this.props.onHandle(field.name, value);
}}
renderInput={(params) => {
return (<TextField {...params} name={field.name} />)
}}
/>
</LocalizationProvider>
{meta.touched && meta.error && (
<div className="error">{meta.error}</div>
)}
</>
)}
</Field>
</div>
{inx === 0 &&
(<span></span>)
}
</span>
))}
</div>
</div>
)}
</FieldArray>
</>
I worked this out
"validation": yup.array().of( yup.object().shape({ firstName: yup.string().min(4, 'too short').required('Required'), lastName: yup.string().min(3, 'cmon').required('Required'), }) ).min(1, 'Minimum of 1 friends')
-- but in the display of errors had to check if it was an array or a string to avoid a render error
under the add more button to display array errors of the main list.
<FormHelperText
error={(form.errors[parent.name] && form.errors[parent.name].length > 0 ? true : false)}
>
{typeof form.errors[parent.name] === "string" &&
<>{form.errors[parent.name]}</>
}
</FormHelperText>
and under the fields - meta errors
{(getHelperVisibility(values, ch)) &&
<FormHelperText
error={meta.touched && (meta.error && meta.error.length > 0 ? true : false)}
>
{meta.error}
</FormHelperText>
}

Quickfilter component width with 100% - Material UI

I'm learning to use Material UI for React js.
I'm implementing the DataGrid control with the Quick filter option.
However, how do I make its width occupy the entire screen?
I didn't find in the documentation if this was possible.
See attached image for better understanding.
Thanks!
<DataGrid
components={{ Toolbar: GridToolbar }}
componentsProps={{
toolbar: {
showQuickFilter: true,
quickFilterProps: { debounceMs: 500 },
},
}}
/>
SampleImage
issue resolved
function QuickSearchToolbar() {
return (
<Box
sx={{
pl: 1,
pr: 1,
pb: 2,
pt: 1,
display: 'flex',
}}
>
<GridToolbarQuickFilter
style={{ flex: 1 }}
quickFilterParser={(searchInput: string) =>
searchInput
.split(',')
.map((value) => value.trim())
.filter((value) => value !== '')
}
debounceMs={600}
/>
</Box>
)
}
<DataGrid
{...rest}
localeText={ptBR.components.MuiDataGrid.defaultProps.localeText}
pageSize={50}
rowsPerPageOptions={[50]}
getRowId={(row) => row.ID}
components={{
Toolbar: QuickSearchToolbar,
LoadingOverlay: LinearProgress
}}
componentsProps={{
toolbar: {
showquickfilter: true,
quickFilterProps: { debounceMs: 600 },
},
}}
/>

Mui Autocomplete with inputLabelProps shrink true in custom theme

When using TextField we can add a custom theme to make the label shrink by default
MuiTextField: {
defaultProps: { InputLabelProps: { shrink: true } },
},
When using it with Autocomplete component.
<Autocomplete
fullWidth
options={options}
clearOnBlur
disablePortal
popupIcon={false}
id="combo-box-demo"
renderInput={params => {
return (
<TextField {...params} label="Movie" variant="standard" />
);
}}
/>
What I have tried is that we can add it in autocomplete renderInput props
renderInput={({ InputLabelProps, params })=> {
return (
<TextField {...params}
label="Movie" variant="standard"
InputLabelProps={{
shrink: true,
...InputLabelProps,
}}
/>
);
}}
but the problem is we need to pass it everytime we want to render the autocomplete and it could be easily forgotten.
It would be convenient if we can also make it default in custom theme.
MuiAutoComplete: {
defaultProps: { InputLabelProps: { shrink: true } },
},
is this possible?
I think you should pass shrink: true in the default props to InputLabel itself like that
MuiInputLabel: {
defaultProps: { shrink: true },
},

How to filter Data in Firebase v9

Hey guys I have a question about how to search/filter data in Firestore and React js would be nice if someone could help.
So let me describe my problem.
First I have created a collection called firearms which contains documents
with the user.uid as well .
And in this document I created a subcollection with auto-generated documents they all have two values the name of the firearm and the name of the manufacturer.
That means if a user has two firearms he stores two documents in the subcollection for each firearm one document.
// firearms/auth.currentUser.uid/firearmssubcollection/auto-IDs
Field values [ name , manufacturer ]
My goal is it to display the ( manufacturer ) from the collection 'firearms' to other users after they search for a specific gun .
If I search with autocomplete lets say for
Baretta
I receive all the Baretta Pistols from the current logged in User but I need the Baretta Pistols from all Users and not just the one from the logged in user.
import React, {useState, useEffect} from 'react';
import { collection, query, where, getDocs } from "firebase/firestore"
import { db, auth } from '../firebaseConfig';
import Autocomplete from '#mui/material/Autocomplete';
function Suche() {
const [kurzHersteller, setKurzHersteller] = useState();
const kurzHerstellerArray = [ 'Andere','Baretta', 'Walther', 'Haenal']
const handleClick = async () => {
const kurzRef = collection(db, `kurzwaffen/${auth.currentUser.uid}/kurzwaffensub`);
const q = query(kurzRef, where("kurzHersteller", "==", `${kurzHersteller}`));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
}
return (
<ThemeProvider theme={theme}>
<Box sx={{ marginLeft: {lg:'15vw', md:'0vw', sm:'0vw', xs:'0vw'}, padding:{lg:4 ,md:4 ,sm:4 , xs:0}, paddingBottom:{lg:2, md:15, sm:10, xs:10}}}>
<Grid container spacing={7} alignItems='center' justifyContent='center' >
<Grid item >
<Card className='CardSuche' sx={{ maxWidth: 700 , height: {lg: 900, md: 900, sm: 750, xs: 750}, backgroundColor:'rgba(39, 39, 39, 0.35)', backdropFilter:'blur(6px)', boxShadow:'0 8px 32px 0 rgba(107, 107, 107, 0.37)' }}>
<CardMedia
component="img"
sx={{height: {lg: 500, md: 500, sm:340 , xs: 340}}}
image="../images/1911.jpg"
/>
<Grid container direction='column' spacing={1}>
<CardContent>
< Grid item>
<Typography gutterBottom variant="h5" component="div" color='white'>
Kurzwaffen
</Typography>
</Grid>
< Grid item >
<Typography variant="body2" color="text.secondary">
<Grid container direction='column' justifyContent='center' alignItems='center' spacing={2}>
<Grid item >
<Paper sx={{width:{lg:550 , md:550 ,sm:360, xs:360}, height: 70 }}>
<Autocomplete
disablePortal
id="combo-box-demo"
options={kurzHerstellerArray}
value={kurzHersteller}
onChange={(_event,value) => setKurzHersteller(value)}
sx={{ width: 300 }}
renderInput={(params) =>
<TextField {...params} label="Hersteller"/>}
/>
</Paper>
</Grid>
</Grid>
</Typography>
</Grid>
</Box>
export default Suche;
match /kurzwaffen/{userId}/kurzwaffensub/{waffenID} {
allow write, delete: if request.auth != null && request.auth.uid == userId;
allow read: if request.auth != null;
}
Here are my security rules for this collection.
Hope you can tell me what I have to change to receive all the weapons instead of only the weapons from the currently logged in user .
Im to dumb to find my mistake ^^.
If you want to search across all kurzwaffensub (sub)collections in the database, you can use a collection group query to do so.
const kurzRef = collectionGroup(db, 'kurzwaffensub');

Material UI Autocomplete + Infinite Scrolling together?

Problem : Getting double Scrollbars - Removing Paper Scrollbar makes the autocomplete content not scrollable hence showing ONLY the contents in the visible height of the dropdown.
If I hide the other scroll then the Infinite Scroll API does not get invoked. How can I get it working :
Description -
I am trying to create a Infinite Scroll with Material UI Autocomplete for which I am using react-infinite-scroll-component attached link for reference
The way I implemented is :
As we need to attach the Infinite Scroll to the Popper that renders the list items; hence I have written my custom PAPER Component (as per documentation it is responsible for rendering items in the dropdown )
PaperComponent={myCustomComponent}
My InfiniteScrollAutoComplete definition is attached below :
<Autocomplete
options={list.data && list.data !== null ? list.data : []}
getOptionLabel={(option) => option.name}
PaperComponent={(param) => (
<InfiniteScroll
height={200}
dataLength={list.total}
next={this.handleFetchNext.bind(this)}
hasMore={list.data.length < list.total ? true : false}
loader={
<p style={{ textAlign: "center", backgroundColor: "#f9dc01" }}>
<b>Loading...</b>
</p>
}
endMessage={
<p style={{ textAlign: "center", backgroundColor: "#f9dc01" }}>
<b>Yay! You have seen it all</b>
</p>
}
>
<Paper {...param} />
</InfiniteScroll>
)}
renderInput={(params) => (
<TextField {...params} label="" variant="outlined" />
)}
/>
const observer = useRef();
const lastOptionElementRef = useCallback((node) => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(async (entries) => {
if (entries[0].isIntersecting && props.hasMore) {
setPageNumber((pageNumber) => pageNumber + 1);
}
});
if (node) observer.current.observe(node);
}, [props.loader]);
you can add this lastOptionElementRef to the last element of the options using the render option prop. This will trigger an function whenever the last option is visible in the viewport. Also, it avoids the scrolling issue