I'm trying to create a price range using mui slider, and 2 text fields for the min and max prices.
I'm getting the numbers correctly in console, the problem is, the slider is not moving in the ui!!
Here's the code on codesandbox:
https://codesandbox.io/s/jolly-stonebraker-er88ri?file=/src/App.js
Here you are trying to change the Max and Min value of the slider which needs to stay as it is. We have to change the value of the slider, in order to move it, not its Min and Max values.
import React, { useState, useEffect } from "react";
import { Stack, Typography, Slider, TextField } from "#mui/material";
export default function App() {
const [minNum, setMinNum] = useState(0);
const [maxNum, setMaxNum] = useState(1000);
const minmin = 0;
const maxmax = 1000;
const [priceRangeValue, setPriceRangeValue] = useState([0, 1000]);
const handlePriceRangeChange = (event, newValue) => {
setMinNum(newValue[0]);
setMaxNum(newValue[1]);
setPriceRangeValue(newValue);
};
console.log(priceRangeValue);
return (
<>
<Slider
getAriaLabel={() => "Price range"}
value={priceRangeValue}
onChange={handlePriceRangeChange}
valueLabelDisplay="auto"
min={minmin}
max={maxmax}
/>
<Stack direction="row" justifyContent="space-evenly" alignItems="center">
<TextField
label="min"
type="number"
variant="outlined"
InputLabelProps={{ shrink: true }}
sx={{ width: "90px" }}
value={minNum}
onChange={(e) => {
setMinNum(Number(e.target.value));
setPriceRangeValue([Number(e.target.value), priceRangeValue[1]]);
}}
/>
<Typography>-</Typography>
<TextField
label="max"
type="number"
variant="outlined"
InputLabelProps={{ shrink: true }}
sx={{ width: "90px" }}
value={maxNum}
onChange={(e) => {
setMaxNum(Number(e.target.value));
setPriceRangeValue([priceRangeValue[0], Number(e.target.value)]);
}}
/>
</Stack>
</>
);
}
Since minNum and maxNum corresponds to priceRangeValue[0] and priceRangeValue[1] respectively.
Therefor we can directly use priceRangeValue and remove the useStates.
import React, { useState, useEffect } from "react";
import { Stack, Typography, Slider, TextField } from "#mui/material";
export default function App() {
const minmin = 0;
const maxmax = 1000;
const [priceRangeValue, setPriceRangeValue] = useState([0, 1000]);
const handlePriceRangeChange = (event, newValue) => {
setPriceRangeValue(newValue);
};
console.log(priceRangeValue);
return (
<>
<Slider
getAriaLabel={() => "Price range"}
value={priceRangeValue}
onChange={handlePriceRangeChange}
valueLabelDisplay="auto"
min={minmin}
max={maxmax}
/>
<Stack direction="row" justifyContent="space-evenly" alignItems="center">
<TextField
label="min"
type="number"
variant="outlined"
InputLabelProps={{ shrink: true }}
sx={{ width: "90px" }}
value={priceRangeValue[0]}
onChange={(e) => {
setPriceRangeValue([Number(e.target.value), priceRangeValue[1]]);
}}
/>
<Typography>-</Typography>
<TextField
label="max"
type="number"
variant="outlined"
InputLabelProps={{ shrink: true }}
sx={{ width: "90px" }}
value={priceRangeValue[1]}
onChange={(e) => {
setPriceRangeValue([priceRangeValue[0], Number(e.target.value)]);
}}
/>
</Stack>
</>
);
}
The min and max properties of the Slider component just mean the minimum and maximum values of that slider, not the minimum and maximum of the range. So you need to remove the following 2 lines in the definition of handlePriceRangeChange function:
setMinNum(newValue[0]);
setMaxNum(newValue[1]);
So, the handlePriceRangeChange function should be as follows:
const handlePriceRangeChange = (event, newValue) => {
setPriceRangeValue(newValue);
};
Related
I've made a custom filter for MUI's datagrid, the filter has two select's which allow you to filter by the column and filter type. The selects are quite big and endup outside the modal, when clicking on an option the whole modal closes, how can I prevent this from happening?
I've used this tutorial - Detect click outside React component to detect clicks outside the filter.
The code below shows the filter and I've also made an codesandbox example here - https://codesandbox.io/s/awesome-panka-g92vhn?file=/src/DataGridCustomFilter.js:0-6708
any help would be appreciated
import React, { useState, useEffect, useRef } from "react";
import {
Button,
Stack,
FormControl,
InputLabel,
Select,
MenuItem,
Paper,
Grid,
IconButton,
TextField,
ClickAwayListener
} from "#material-ui/core";
import FilterListIcon from "#mui/icons-material/FilterList";
import AddIcon from "#mui/icons-material/Add";
import CloseIcon from "#mui/icons-material/Close";
import { useForm, useFieldArray, Controller } from "react-hook-form";
import { columns } from "./columns";
const filterTypes = {
string: ["contains", "equals", "starts with", "ends with", "is any of"],
int: ["contains", "equals", "less than", "greater than"]
};
function FilterRow({
len,
setOpen,
field,
control,
columns,
index,
handleRemoveFilter
}) {
return (
<Grid container spacing={0}>
<Grid
item
md={1}
style={{
display: "flex",
alignSelf: "flex-end",
alignItems: "center"
}}
>
<IconButton
size="small"
onClick={() => {
if (len === 1) {
setOpen(false);
} else {
console.log(index, "---");
handleRemoveFilter(index);
}
}}
>
<CloseIcon style={{ fontSize: "20px" }} />
</IconButton>
</Grid>
<Grid item md={4}>
<Controller
name={`filterForm.${index}.column`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl variant="standard" sx={{ width: "100%" }}>
<InputLabel>Column</InputLabel>
<Select
value={value}
onChange={onChange}
label="Column"
defaultValue=""
>
{columns.map((a) => {
return a.exclude_filter === true ? null : (
<MenuItem value={a.headerName}>{a.headerName}</MenuItem>
);
})}
</Select>
</FormControl>
)}
/>
</Grid>
<Grid item md={3}>
<Controller
name={`filterForm.${index}.filter`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl variant="standard" sx={{ width: "100%" }}>
<InputLabel>Filter</InputLabel>
<Select
value={value}
onChange={onChange}
label="Filter"
defaultValue=""
>
{filterTypes.string.map((a) => {
return <MenuItem value={a}>{a}</MenuItem>;
})}
</Select>
</FormControl>
)}
/>
</Grid>
<Grid item md={4}>
<Controller
name={`filterForm.${index}.value`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl>
<TextField
onChange={onChange}
value={value}
label="Value"
variant="standard"
/>
</FormControl>
)}
/>
{/* )} */}
</Grid>
</Grid>
);
}
function DataGridCustomFilter() {
const { control, handleSubmit } = useForm();
const { fields, append, remove } = useFieldArray({
control,
name: "filterForm"
});
const [open, setOpen] = useState(false);
const onSubmit = (data) => {};
useEffect(() => {
if (fields.length === 0) {
append({
column: "ID",
filter: filterTypes.string[0],
value: ""
});
}
}, [fields]);
const [clickedOutside, setClickedOutside] = useState(false);
const myRef = useRef();
const handleClickOutside = (e) => {
if (myRef.current && !myRef.current.contains(e.target)) {
setClickedOutside(true);
setOpen(!open);
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
});
return (
<>
<Button
startIcon={<FilterListIcon />}
size="small"
onClick={() => {
setOpen(!open);
}}
// disabled={isDisabled}
>
FILTERS
</Button>
{open ? (
<div ref={myRef}>
<Paper
style={{
width: 550,
padding: 10,
zIndex: 1300,
position: "absolute",
inset: "0px auto auto 0px",
margin: 0,
display: "block"
// transform: "translate3d(160.556px, 252.222px, 0px)",
}}
variant="elevation"
elevation={5}
>
<form onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={0.5}>
<div style={{ maxHeight: 210, overflow: "scroll" }}>
{fields.map((field, index) => {
return (
<div style={{ paddingBottom: 5 }}>
<FilterRow
len={fields.length}
control={control}
setOpen={setOpen}
field={field}
columns={columns}
handleRemoveFilter={() => remove(index)}
{...{ control, index, field }}
// handleClickAway={handleClickAway}
/>
</div>
);
})}
</div>
<div style={{ marginTop: 10, paddingLeft: 40 }}>
<Stack direction="row" spacing={1}>
<Button size="small" startIcon={<AddIcon />}>
ADD FILTER
</Button>
<Button size="small" type="submit">
{fields.length > 1 ? "APPLY FILTERS" : "APPLY FILTER"}
</Button>
</Stack>
</div>
</Stack>
</form>
</Paper>
</div>
) : null}
</>
);
}
export default DataGridCustomFilter;
So far I've tried MUI's ClickAwayListener and the example above, both seem to give the same result
DataGrid component uses NativeSelect. I have checked your codesandbox and tried replacing Select to NativeSelect and MenuItem to Option. filter is working properly. below is sample code for update.
...
<NativeSelect
value={value}
onChange={onChange}
label="Column"
defaultValue=""
>
{columns.map((a) => {
return a.exclude_filter === true ? null : (
<option value={a.headerName}>{a.headerName}</option >
);
})}
</NativeSelect>
...
I'm new with react form, I'm using Material UI and Controller Component, and I'm sending a React Hook form request but not getting any response, form's (HTML form tag) onSubmit event is occurring but handleSubmit is not working I have one more form like that it is working perfectly fine but I don't know why it's not working, can anybody please help me with that
import { Button, useTheme, Grid, TextField, Typography } from '#mui/material';
import WSSelectBox from 'components/common/WSSelect';
import React, { FC } from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { isMobile } from 'utils/mediaqueries';
import CheckBoxButton from '../CheckBoxButton';
import { formTypes } from './utils';
import { yupResolver } from '#hookform/resolvers/yup';
import * as yup from 'yup';
import { FormPropTypes } from './type';
const schema = yup
.object()
.shape({
name: yup.string().required(),
residentialCountry: yup.number().required(),
initiator: yup.string().required(),
program: yup.string().required(),
list: yup.string().required(),
})
.required();
const Entities: FC<FormPropTypes> = ({
handleClick,
selectedType,
handleSearch,
}) => {
const theme = useTheme();
const methods = useForm({
resolver: yupResolver(schema),
});
const { handleSubmit, control } = methods;
const onSubmit = (data) => {
// Backend is not done yet
console.log('DataData', data);
};
return (
<FormProvider {...methods}>
<form
onSubmit={(e) => {
e.preventDefault();
console.log('skdjskd', 'Line no 44');
handleSubmit(onSubmit);
}}
>
<Grid container spacing={'16px'}>
{formTypes.map((type) => (
<Grid item xs={6} sm={'auto'} md={'auto'} key={type}>
<CheckBoxButton
key={type}
name={'type'}
value={type}
handleClick={handleClick}
active={type == selectedType ? true : false}
/>
</Grid>
))}
</Grid>
<Grid container pt={4} columnSpacing="20px" rowSpacing={'16px'}>
<Grid item xs={12} sm={12} md={6}>
<Controller
name="name"
render={({
// eslint-disable-next-line #typescript-eslint/no-unused-vars
field: { value, ...otherFieldProps },
fieldState,
}) => (
<TextField
fullWidth
id="sanctions-form-name"
label="Name"
variant="outlined"
helperText={
<p
style={{
position: 'relative',
left: -13,
fontSize: 12,
}}
>
Try to enter the full name or part of it. It is possible
to use original language or the Latin alphabet.
</p>
}
required
error={!!fieldState.error}
{...otherFieldProps}
/>
)}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
id="sanctions-form-residential-country"
label="Residential country"
name={'residentialCountry'}
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
data={['Ten', 'Twenty']}
handleSelect={() => {}}
id="sanctions-form-initiator"
name={'initiator'}
label="Initiator"
type="text"
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-program"
label="Program"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type="text"
name={'program'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-list"
label="List"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
name={'list'}
control={control}
/>
</Grid>
</Grid>
<Grid
container
pt={{ xs: '20px', md: '30px' }}
rowSpacing="10px"
alignItems="center"
sx={{
[isMobile(theme)]: {
textAlign: 'center',
},
}}
justifyContent="left"
>
<Grid item xs={6} sm={'auto'}>
<Button
variant="contained"
color="primary"
sx={{
minWidth: '200px',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Search
</Button>
</Grid>
<Grid item xs={6} sm={'auto'}>
<Button
sx={{
minWidth: '200px',
color: '#3883FA',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Reset
</Button>
</Grid>
</Grid>
</form>
<Typography
variant="body2"
sx={{ fontSize: 17, color: '#121E3D', marginTop: '20px' }}
>
Use filters to start your search.
</Typography>
</FormProvider>
);
};
export default Entities;
SELECT BOX
import { TextField, MenuItem, styled, Select } from '#mui/material';
import { Controller, useForm } from 'react-hook-form';
export type SelectBoxProps = {
label: string;
id: string;
data: Array<string>;
handleSelect: VoidFunction;
type: string;
Control: () => {};
};
const SelectBox = styled(TextField)`
& .MuiOutlinedInput-root:focus {
&.Mui-focused fieldset {
border-bottom: none !important;
}
}
`;
const WSSelectBox = ({
label,
id,
data,
handleSelect,
name,
type,
control,
}) => {
return (
<>
<Controller
name={name}
render={({ field }) => (
<SelectBox
defaultValue=""
fullWidth
autoComplete="off"
id={id}
type={type}
label={label}
variant="outlined"
required
select
{...field}
>
{data.map((opt) => (
<MenuItem key={opt} value={opt}>
{opt}
</MenuItem>
))}
</SelectBox>
)}
control={control}
/>
</>
);
};
export default WSSelectBox;
I was making a dialog which has two tabs named Address and Map, which allows the user to enter city name and street name in two different textfields in address tab and be able to pinpoint or auto-locate the location in the map. In map tab I was using react-leaflet map to show the map itself to the user, so far so good but after switching between tabs the map changes to a monotonic gray image. zoom in and out won't help it!
Code:
import * as React from 'react';
import { useEffect, useState } from 'react';
import Button from '#mui/material/Button';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import useMediaQuery from '#mui/material/useMediaQuery';
import CloseIcon from '#mui/icons-material/CloseOutlined';
import { Divider, IconButton, InputLabel, } from '#mui/material';
import { Box, Grid, Tab, TextField, useTheme } from '#material-ui/core';
import { TabContext, TabList, TabPanel } from '#mui/lab';
import "leaflet/dist/leaflet.css";
import icon from "../../../../Account/components/constants";
import { MapContainer, TileLayer, Marker, useMapEvents, } from 'react-leaflet'
const useGeoLocation = () => {
// this function will allow the user to get the current location of the device!
const [location, setLocation] = useState({
loaded: false,
coordinates: { lat: "", lng: "" }
});
const onSuccess = (location) => {
setLocation({
loaded: true,
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude,
}
});
};
const onError = (error) => {
setLocation({
loaded: true,
error,
});
};
useEffect(() => {
if (!("geolocation" in navigator)) {
onError({
code: 0,
message: "Your device GPS is OFF!",
});
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}, []);
return location;
}
export default function AddressDialog() {
// Genral Properties!
const [open, setOpen] = useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [value, setValue] = useState(0);
// Address Tab Properties!
const [city, setCity] = useState("");
const [street, setStreet] = useState();
// Map Properties!
const [initializerPos,] = useState([40.689247, -74.044502]);
const [position, setPosition] = useState(initializerPos);
const [mapState, setMapState] = useState({
position: position,
map: null
});
const zoom_level = 18;
const location = useGeoLocation();
// Arrow funcitons!
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setValue(0);
};
const handleSubmit = () => {
// api update in here
}
const showMyLocation = () => {
if (location.loaded && !location.error) {
let pos = [location.coordinates.lat, location.coordinates.lng];
setPosition([location.coordinates.lat, location.coordinates.lng]);
setMapState((state) => ({
...state,
position: pos,
}));
const { map } = mapState;
if (map) {
map.flyTo(pos, zoom_level);
}
} else {
if (location.error) {
alert(location.error.message)
}
else {
alert("Problem in loading curent location!")
}
}
};
function AddMarkerToClick() {
const [markers, setMarkers] = useState([]);
useMapEvents({
click(e) {
const newMarker = e.latlng
setMarkers([...markers, newMarker]);
setPosition([e.latlng.lat, e.latlng.lng]);
setMapState((state) => ({
...state,
position: newMarker,
}));
const { map } = mapState;
if (map)
{
map.flyTo(newMarker, zoom_level);
}
},
});
return null
};
return (
<div dir="ltr">
<Button onClick={handleClickOpen} variant="contained" type="button" aria-label="Edit Info" fullWidth size="small">
Edit Address Info
</Button>
<Dialog fullScreen={fullScreen} open={open} aria-labelledby="responsive-dialog-title">
<DialogTitle>
<IconButton onClick={handleClose} aria-label="Close Dialog">
<CloseIcon fontSize="medium" />
</IconButton>
</DialogTitle>
<Divider />
<DialogTitle>Edit Address</DialogTitle>
<DialogContent id ="dialogContent" >
<DialogContentText>
In this section you are able to edit your address info
</DialogContentText>
<TabContext value={value.toString()} >
<Box >
<TabList
onChange={(event, newValue) => { setValue(parseInt(newValue, 10));}}
aria-label="address-map-tab">
<Tab label="Address" value="0" />
<Tab label="Map" value="1" />
</TabList>
</Box>
<TabPanel value="0">
<Grid container spacing={theme.spacing(0)}
>
<Grid item xs={12} sm={6}>
<TextField value={city} onChange={(e) => setCity(e.target.value)} margin="normal" variant="outlined"
required
fullWidth
type="text"
name="area"
id="area"
label={"city"}
placeholder={"ex: New York"}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
value={street}
onChange={(e) => setStreet(e.target.value)}
margin="normal"
variant="outlined"
required
fullWidth
type="text"
name="street"
id="street"
label={"Streen Name"}
placeholder={"ex: wall street"}
/>
</Grid>
</Grid>
</TabPanel>
<TabPanel value="1">
<Grid container>
<div style={{
marginLeft: "auto",
marginRight: "auto",
width: "100%"
}}>
<InputLabel>
Your location in map:
</InputLabel>
<MapContainer
center={mapState.position}
zoom ={15}
scrollWheelZoom
style={{
height: fullScreen ? 200 : 350,
width: fullScreen ? "100%" : "100%",
textAlign: "center",
marginLeft: "auto",
marginRight: "auto",
marginTop: theme.spacing(1)
}}
whenCreated={map => setMapState({ map })}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AddMarkerToClick />
{
position && (
<Marker position={position} icon={icon}></Marker>
)
}
</MapContainer>
<Button variant="outlined" color="primary" size="large" onClick={showMyLocation}>
Here!
</Button>
</div>
</Grid>
</TabPanel>
</TabContext>
</DialogContent>
<DialogActions style={{ marginLeft: theme.spacing(2), marginRight: theme.spacing(2) }}>
<Grid container direction="row" spacing={1}>
<Grid item container xs={4} dir="left" justifyContent="flex-end">
<Button variant="contained" type="button" color="error" fullWidth
name="cancel-btn" onClick={handleClose}
>
Cancel
</Button>
</Grid>
<Grid item container xs={8} >
<Button variant="contained" type="button" color="primary" fullWidth
name="submit-btn" onClick={handleSubmit} >
Save
</Button>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</div>
);
After switching between tabs, the map grayed out, and shows nothing!
Then interacting with map, e.g, clicking on it, zoom in or out results the error!
Uncaught Error: Set map center and zoom first.
My Solution:
What I did is to save the current (after first interaction with map) state of the map and then try to restart it from saved state for future use (switching to other tabs/views).
To save the state of the map, It should happen right exactly before switching out from the map view! In this case before switching back to address tab or closing The Dialog.
Fixed Code:
import * as React from 'react';
import { useEffect, useState } from 'react';
import Button from '#mui/material/Button';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import useMediaQuery from '#mui/material/useMediaQuery';
import CloseIcon from '#mui/icons-material/CloseOutlined';
import { Divider, IconButton, InputLabel, } from '#mui/material';
import { Box, Grid, Tab, TextField, useTheme } from '#material-ui/core';
import { TabContext, TabList, TabPanel } from '#mui/lab';
import "leaflet/dist/leaflet.css";
import icon from "../../../../Account/components/constants";
import { MapContainer, TileLayer, Marker, useMapEvents, } from 'react-leaflet'
const useGeoLocation = () => {
// this function will allow the user to get the current location of the device!
const [location, setLocation] = useState({
loaded: false,
coordinates: { lat: "", lng: "" }
});
const onSuccess = (location) => {
setLocation({
loaded: true,
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude,
}
});
};
const onError = (error) => {
setLocation({
loaded: true,
error,
});
};
useEffect(() => {
if (!("geolocation" in navigator)) {
onError({
code: 0,
message: "Your device GPS is OFF!",
});
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}, []);
return location;
}
export default function AddressDialog() {
// Genral Properties!
const [open, setOpen] = useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [value, setValue] = useState(0);
// Address Tab Properties!
const [city, setCity] = useState("");
const [street, setStreet] = useState();
// Map Properties!
const [initializerPos,] = useState([40.689247, -74.044502]);
const [position, setPosition] = useState(initializerPos);
const [mapState, setMapState] = useState({
position: position,
map: null
});
const zoom_level = 18;
const location = useGeoLocation();
// Two new properties to overcome the gray out problem.
const initializeZoom_level = 15;
const [mapZoom, setMapZoom] = useState(initializeZoom_level);
// Arrow funcitons!
const stabilizeMapData = (isItADialogClose ) => {
setMapZoom(isItADialogClose ? initializeZoom_level : mapZoom);
setPosition(isItADialogClose ? initializerPos : position);
setMapState({
position: isItADialogClose ? initializerPos : position,
map: null
});
}
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
stabilizeMapData(true); // The user is about to close The Dialog!
setOpen(false);
setValue(0);
};
const handleSubmit = () => {
// api update in here
}
const showMyLocation = () => {
if (location.loaded && !location.error) {
let pos = [location.coordinates.lat, location.coordinates.lng];
setPosition([location.coordinates.lat, location.coordinates.lng]);
setMapState((state) => ({
...state,
position: pos,
}));
const { map } = mapState;
if (map) {
map.flyTo(pos, zoom_level);
setMapZoom(zoom_level);
}
} else {
if (location.error) {
alert(location.error.message)
}
else {
alert("Problem in loading curent location!")
}
}
};
function AddMarkerToClick() {
const [markers, setMarkers] = useState([]);
useMapEvents({
click(e) {
const newMarker = e.latlng
setMarkers([...markers, newMarker]);
setPosition([e.latlng.lat, e.latlng.lng]);
setMapState((state) => ({
...state,
position: newMarker,
}));
const { map } = mapState;
if (map)
{
map.flyTo(newMarker, zoom_level);
setMapZoom(zoom_level);
}
},
});
return null
};
return (
<div dir="ltr">
<Button onClick={handleClickOpen} variant="contained" type="button" aria-label="Edit Info" fullWidth size="small">
Edit Address Info
</Button>
<Dialog fullScreen={fullScreen} open={open} aria-labelledby="responsive-dialog-title">
<DialogTitle>
<IconButton onClick={handleClose} aria-label="Close Dialog">
<CloseIcon fontSize="medium" />
</IconButton>
</DialogTitle>
<Divider />
<DialogTitle>Edit Address</DialogTitle>
<DialogContent id ="dialogContent" >
<DialogContentText>
In this section you are able to edit your address info
</DialogContentText>
<TabContext value={value.toString()} >
<Box >
<TabList
onChange={(event, newValue) => {
if (value === 1) {
// if it is in The Map Tab and It's about to switch the tab!
stabilizeMapData(false);
}
setValue(parseInt(newValue, 10));
}}
aria-label="address-map-tab">
<Tab label="Address" value="0" />
<Tab label="Map" value="1" />
</TabList>
</Box>
<TabPanel value="0">
<Grid container spacing={theme.spacing(0)}
>
<Grid item xs={12} sm={6}>
<TextField value={city} onChange={(e) => setCity(e.target.value)} margin="normal" variant="outlined"
required
fullWidth
type="text"
name="area"
id="area"
label={"city"}
placeholder={"ex: New York"}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
value={street}
onChange={(e) => setStreet(e.target.value)}
margin="normal"
variant="outlined"
required
fullWidth
type="text"
name="street"
id="street"
label={"Streen Name"}
placeholder={"ex: wall street"}
/>
</Grid>
</Grid>
</TabPanel>
<TabPanel value="1">
<Grid container>
<div style={{
marginLeft: "auto",
marginRight: "auto",
width: "100%"
}}>
<InputLabel>
Your location in map:
</InputLabel>
<MapContainer
center={mapState.position}
zoom={mapZoom}
scrollWheelZoom
style={{
height: fullScreen ? 200 : 350,
width: fullScreen ? "100%" : "100%",
textAlign: "center",
marginLeft: "auto",
marginRight: "auto",
marginTop: theme.spacing(1)
}}
whenCreated={map => setMapState({ map })}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AddMarkerToClick />
{
position && (
<Marker position={position} icon={icon}></Marker>
)
}
</MapContainer>
<Button variant="outlined" color="primary" size="large" onClick={showMyLocation}>
Here!
</Button>
</div>
</Grid>
</TabPanel>
</TabContext>
</DialogContent>
<DialogActions style={{ marginLeft: theme.spacing(2), marginRight: theme.spacing(2) }}>
<Grid container direction="row" spacing={1}>
<Grid item container xs={4} dir="left" justifyContent="flex-end">
<Button variant="contained" type="button" color="error" fullWidth
name="cancel-btn" onClick={handleClose}
>
Cancel
</Button>
</Grid>
<Grid item container xs={8} >
<Button variant="contained" type="button" color="primary" fullWidth
name="submit-btn" onClick={handleSubmit} >
Save
</Button>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</div>
);
}
I did some comments in the code to demonstrate the solution. If you know a better solution to this problem I looking forward to see it.
I would like when clicking on my accordion, the data in this line will go into the form of my dialog box. But I am not receiving any data in the form.
Why is the form not receiving the data?
import React, { useEffect, useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
Avatar,
Box,
Card,
Accordion,
AccordionSummary,
AccordionDetails,
Grid,
SvgIcon,
InputAdornment,
CardContent,
TextField,
ListItemText,
ListItem,
List,
Checkbox,
Table,
TableBody,
TableCell,
TableHead,
TablePagination,
IconButton,
Typography,
makeStyles,
Button
} from '#material-ui/core';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import getInitials from 'src/utils/getInitials';
import EditProjAdminE from './editProjAdminE';
import AjoutEven from './ajoutEven';
import dataEven from './data';
import SpeedDialTooltipOpen from './speedDialE';
import EditIcon from '#material-ui/icons/Edit';
import AddIcon from '#material-ui/icons/Add';
import { Search as SearchIcon } from 'react-feather';
import { Slide } from 'react-slideshow-image';
import axios from "axios";
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {},
absolute: {
position: 'absolute',
bottom: theme.spacing(2),
right: theme.spacing(3),
},
avatar: {
marginRight: theme.spacing(2)
}
}));
const ProjetAdminE = ({ className, dataEleve, ...rest }) => {
const classes = useStyles();
// const [data, setData] = useState(dataEven);
const [filteredEven, setFilteredEven] = useState([]);
const [dataSearch, setDataSearch] = useState([]);
const [loading, setLoading] = useState(false);
const [limit, setLimit] = useState(10);
const [page, setPage] = useState(0);
const [selectedeleveIds, setSelectedeleveIds] = useState([]);
// const dateR = new Date()
// const dateReel = dateR.setDate(dateR.getDate()+1);
const handleLimitChange = (event) => {
setLimit(event.target.value);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
const [search, setSearch] = useState('');
useEffect(() => {
setLoading(true);
axios
.get("http://localhost:8080/employees")
.then((res) => {
setDataSearch(res.data);
setLoading(false);
})
.catch((err) => {
console.log(err);
});
}, []);
const suppression = (id) => {
fetch('http://localhost:8080/evenement/' + id, {
method: 'DELETE',
})
.then(res => res.text())
.then(res => {
// setDataSearch(res.data);
console.log(res)
})
alert(JSON.stringify("événement Numéro " + id + " supprimé"))
}
// const modification =(id) =>{
// fetch('http://localhost:8080/update/' + id, {
// method: 'PUT',
// })
// .then(res => res.text())
// .then(res => console.log(res))
// alert(JSON.stringify("événement Numéro " +id+ " modifié"))
// }
// alert(JSON.stringify(index))
useEffect(() => {
setFilteredEven(
dataSearch.filter((Evenen) =>
Evenen.descrip_evene.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, dataSearch]);
return (
<Card
className={clsx(classes.root, className)}
{...rest}
>
<>
<Box
display="flex"
justifyContent="left"
style={{ height: 30 }}
>
<Typography variant="h3" style={{ margin: 10, color: '#1565C0' }}>
LISTE DES EVENEMENTS
</Typography>
</Box>
<Box mt={3}>
<Card>
<CardContent>
<Box maxWidth={500}>
<TextField
value={search}
onChange={e => {
setSearch(e.target.value);
}}
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SvgIcon
fontSize="small"
color="action"
>
<SearchIcon />
</SvgIcon>
</InputAdornment>
)
}}
placeholder="Recherchez un évenement"
variant="outlined"
/>
</Box>
{/* <Button
color="primary"
variant="contained"
onClick = {alert(JSON.stringify(dateReel))}
>
Rechercher
</Button> */}
</CardContent>
</Card>
</Box>
<Grid>
<Grid spacing={1} md={8} xs={12} style={{ margin: 2 }}>
{filteredEven.map((recherche, index) => (
<Accordion style={{ marginTop: 30 }} >
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
style={{ backgroundColor: '#DADFD9' }}
>
<Grid container spacing={1} md={12} xs={12} style={{ margin: 0 }}>
<Grid item md={2} xs={4}>
{recherche.date_even.slice(0, 10)}
</Grid>
<Grid item md={2} xs={2}>
{recherche.prix_even}
</Grid>
<Grid item md={2} xs={3}>
{recherche.statut}
</Grid>
<Grid item md={3} xs={3}>
{recherche.descrip_evene}
</Grid>
<Grid item md={3} xs={8} style={{ marginTop: -10 }}>
<IconButton>
<EditProjAdminE
dataSearch={dataSearch}
setDataSearch={setDataSearch}
id={recherche.id}
/>
</IconButton>
<IconButton
onClick={async () => {
suppression(recherche.id)
window.location.reload(false)
}}
>
<DeleteIcon fontSize="small" style={{ color: 'black' }} />
</IconButton>
{/* <SpeedDialTooltipOpen/> */}
</Grid>
</Grid>
</AccordionSummary>
<AccordionDetails>
<List>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.id}
</Typography>
}
secondary="Membre concerné"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.lieu}
</Typography>
}
secondary="Lieu"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.heure}
</Typography>
}
secondary="Heure"
/>
</ListItem>
</List>
</AccordionDetails>
</Accordion>
))}
</Grid>
</Grid>
<AjoutEven />
</>
</Card>
);
};
// Results.propTypes = {
// className: PropTypes.string,
// dataEleve: PropTypes.array.isRequired
// };
export default ProjetAdminE;
editProjetEven.js
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import { makeStyles, useTheme, withStyles } from '#material-ui/core/styles';
import {
Button,
Grid,
MenuItem,
DialogContent,
DialogActions,
Dialog,
IconButton,
Avatar,
TextField,
DialogTitle,
} from '#material-ui/core';
import getInitials from 'src/utils/getInitials';
import CreateIcon from '#material-ui/icons/Create';
import EditIcon from '#material-ui/icons/Edit';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {
width: 645,
},
item: {
height: 50
},
buttonDial: {
color: "#fff",
},
buttonAnnuler: {
color: "red"
},
buttonSave: {
background: "#558b2f",
color: "#558b2f",
}
}));
export default function EditProjAdminE(setDataSearch,dataSearch,data,setData,id,index) {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [opens, setOpens] = React.useState(false);
const handleChange = event => {
const { name, value } = event.target
setDataSearch({ ...dataSearch, [name]: value })
}
// const fullScreen = useMediaQuery(theme.breakpoints.down(645));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
// const handleInputChange = event => {
// const { name, value } = event.target
// setData({ ...data, [name]: value })
// }
// const item = dataSearch.find(id);
return (
<div>
<div display="flex">
<IconButton onClick={handleClickOpen}>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
</div>
<Dialog
fullWidth
// fullScreen
open={open }
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
maxWidth = 'md'
>
{/* { index ==="" ? "aucune information":
<> */}
<DialogTitle id="responsive-dialog-title">Virement</DialogTitle>
<DialogContent >
<Grid container spacing={1}>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="prix_even"
value={dataSearch.prix_even}
// defaultValue={dataSearch.prix_even}
label="Prix"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="heure"
value={dataSearch.heure}
label="Heure"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="lieu"
value={dataSearch.lieu}
label="Lieu"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="date"
name="date_even"
value={dataSearch.date_even}
helperText="Date de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="descrip_even"
value={dataSearch.descrip_even}
label="Descr de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="statut"
value={dataSearch.statut}
label="Statut"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
// onClick={alert(JSON.stringify(dataSearch))}
>
Modifier
</Button>
<Button onClick={handleClose} className={classes.buttonAnnuler}>
Fermer
</Button>
</DialogActions>
{/* </>
} */}
</Dialog>
</div>
);
}
on click I pass the index of the object to the array and send it to a new array that I created
<IconButton onClick={async () => {
setData({ ...dataSearch[index] })
handleClickOpen()
}}
>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
The handleClickOpen seems to be only opening the dialog box and not invoking setDataSearch({ ...dataSearch, [name]: value }) which seems to be responsible to add values to the dataSearch object that is used in your form fields.
I would personally double check if the EditProjAdminE component is receiving the proper dataSearch and then later call a similar function to handleChange when the open event is triggered.
I am new to Material UI. So, here i am using a Textfield type Date. By defaut in the textfield it shows "dd-mm-yyyy". But, i want to show an string value by default, like this "Add DOB (MM/DD/YYYY)". I tried some ways, its not taking the string value. Please let me know, how can i achieve this.
import React from 'react';
import { render } from 'react-dom';
import TextField from 'material-ui/TextField';
const App = () => (
<div style={styles}>
<TextField
id="date"
label="Add Date of Birth"
type="date"
name="DateOfBirth"
defaultValue="Add DOB"
className="form-field"
InputLabelProps={{
shrink: true,
}}
/>
</div>
);
render(<App />, document.getElementById('root'));
I'm not sure what default you are asking. I am assuming two things here: default value for the date or some kind of text accompanying the date.
If you want to set default value for the TextField it is best to set the value prop for the component with a state as in value={stateValue}. If you want to add some text to accompany the date you can try Input Adornments in the Material UI.
Code example for this:
import React from "react";
import InputAdornment from "#material-ui/core/InputAdornment";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
container: {
display: "flex",
flexDirection: "column",
flexWrap: "wrap"
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 200
},
adornment: {
width: 110
},
dense: {
marginTop: 19
},
menu: {
width: 200
}
}));
export default function TextFields() {
const classes = useStyles();
const [values, setValues] = React.useState({
date: "1993-11-01"
});
const handleChange = name => event => {
console.log(event.target.value);
setValues({ ...values, [name]: event.target.value });
};
return (
<form className={classes.container} noValidate autoComplete="off">
<TextField
id="date"
label="Add Date of Birth"
type="date"
name="DateOfBirth"
// defaultValue="Add DOB"
InputProps={{
startAdornment: (
<InputAdornment className={classes.adornment} position="start">
Add DOB
</InputAdornment>
)
}}
value={values.date}
className={classes.textField}
onChange={handleChange("date")}
InputLabelProps={{
shrink: true
}}
/>
<TextField
id="standard-name"
label="Date Text"
className={classes.textField}
value={values.date}
onChange={handleChange("date")}
margin="normal"
/>
</form>
);
}
Demo Codesandbox: TextField - date