I am trying to show and hide the 2nd tab programmatically yet when I click on the 3rd tab I see the content of the 2nd tab.
Providing my code snippet and sandbox below
Can someone please help?
https://codesandbox.io/s/material-demo-8je9d
export default function SimpleTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const [Tab2Visible] = useState(false);
useEffect((newValue) => {
// const { user } = props;
console.log("useEffect newValue--->", newValue);
}, []);
const handleChange = (event, newValue) => {
console.log("newValue--->", newValue);
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs
value={value}
onChange={handleChange}
aria-label="simple tabs example"
>
<Tab label="Item One" {...a11yProps(0)} />
{Tab2Visible === false ? (
""
) : (
<Tab label="Item Two" {...a11yProps(1)} />
)}
<Tab label="Item Three" {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
);
}
If you do not provide any value property to the Tab component, MaterialUI defaults it to the index of the rendered items. Since only two Tab elements are rendered, the handleChange function gives value as 1 for Tab item 3.
Adding an explicit value property will work the way you want it to
<Tabs
value={value}
onChange={handleChange}
aria-label="simple tabs example"
>
<Tab label="Item One" value={0} {...a11yProps(0)} />
{Tab2Visible === false ? (
""
) : (
<Tab label="Item Two" value={1} {...a11yProps(1)} />
)}
<Tab label="Item Three" value={2} {...a11yProps(2)} />
</Tabs>
Working DEMO
Related
I have a form built with Formik containing an array of objects. When I add a second element to the form with the add-button, I get the following error:
Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
I have made sure that initial values is defined for the the form. I use the FieldArray component from formik. If I remove the time and rate fields, so it's only the name input in each object, I don't get the error, but when I add the time and rate fields, the error occurs. The component contains the following:
const TimeItemsForm = () => {
const jiraItemsStore = useJiraItemsStore();
function jiraTimeImported(timeItemIndex: number, importedHoursTotal: number, checkedItems: CheckedTimeItems) {
// Add checked items to store
jiraItemsStore.setJiraTable(timeItemIndex, checkedItems, importedHoursTotal);
}
const TimeItemSchema = Yup.object().shape({
name: Yup.string().required('Required'),
time: Yup.number().min(0).required('Required'),
// rate: Yup.number().min(0).required('Required'),
});
const TimeItemsSchema = Yup.object().shape({
timeItems: Yup.array().of(TimeItemSchema),
})
const initialValues = {
timeItems: [
{
name: '',
time: 0,
rate: 0,
},
],
};
return (
<>
<Formik
validateOnChange={false}
initialValues={initialValues}
validationSchema={TimeItemsSchema}
onSubmit={(values) => console.log(values)}>
{({ values, errors, touched }) => (
<Form onChange={() => console.log("hs")}>
<FieldArray
name="timeItems"
render={arrayHelpers => (
<div>
{values.timeItems && values.timeItems.length > 0 ? (
values.timeItems.map((timeItem, index) => (
<React.Fragment key={index}>
<Stack gap={2}>
<Flex alignItems="end" gap={4}>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].name">Name</FormLabel>
<Field as={Input} placeholder="Time Item Name" variant="filled" name={`timeItems[${index}].name`} />
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].time">Time</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="0 Hours" variant="filled" name={`timeItems[${index}].time`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].rate">Rate</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="USD 0" variant="filled" name={`timeItems[${index}].rate`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<Flex flexShrink="0" gap={3} direction="column">
<Heading fontWeight="normal" size="sm">Apply Taxes & Discounts</Heading>
<Flex mb={0.5} gap={4}>
<Tooltip label='Tax 1' fontSize='sm'>
<IconButton variant={true ? 'solid' : 'outline'} aria-label='Tax' icon={<TbReceipt />} />
</Tooltip>
<IconButton variant='outline' aria-label='Discount' icon={<TbDiscount />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Flex>
<Flex py={2} gap={10} justifyContent="space-between">
<TimeItemsTable timeItemIndex={index} jiraTimeImported={jiraTimeImported} />
<Flex gap={4}>
<IconButton aria-label='Create Time Item' icon={<MinusIcon />} onClick={() => arrayHelpers.remove(index)} />
<IconButton aria-label='Create Time Item' icon={<AddIcon />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Stack>
<Divider my={4} />
</React.Fragment>
))
) : (
<button type="button" onClick={() => arrayHelpers.push('')}>
Add a Time Item
</button>
)}
<Flex mt={6} gap={10} justifyContent="space-between">
<Button colorScheme="purple" type="submit">Save</Button>
{/* <TimeItemsStats /> */}
</Flex>
</div>
)}
/>
</Form>
)}
</Formik>
</>
)
}
Solution:
The arrayHelpers.push and arrayHelpers.insert didn't insert the values with the correct type, as seen in the code.
I have a vertical tab and Next and Back buttons like in my react application. i want to move forward and backward tab using button click like stepper. if i click "next button" move to next tab. and the same if i click "back button" move to back tab.
and additionally, how to get data from this all tabs?
here is my tried code..
import React from "react";
import { useState } from "react";
export default function Products() {
const [value, setValue] = React.useState(0);
//Next tab button
function getSteps() {
return ["Shirt", "Hoodies", "Jeans", "Inner wear"];
}
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleReset = () => {
setActiveStep(0);
};
const handleChange = (event, newValue) => {
setValue(newValue);
};
<Tabs
orientation="vertical"
variant="scrollable"
value={value}
onChange={handleChange}
aria-label="Vertical tabs"
activeStep={activeStep}
>
<Tab label="Shirt" {...a11yProps(0)} />
<Tab label="Hoodies" {...a11yProps(1)} />
<Tab label="Jeans" {...a11yProps(2)} />
<Tab label="Inner wear" {...a11yProps(3)} />
</Tabs>
<Form>
<TabPanel value={value} index={0}>Tab 1</TabPanel>
<TabPanel value={value} index={1}>Tab 2</TabPanel>
<TabPanel value={value} index={2}>Tab 3</TabPanel>
<TabPanel value={value} index={3}>Tab 4</TabPanel>
</Form>
{/* NEXT & SAVE BUTTONS */}
<Grid>
{activeStep === steps.length ? (
<div>
<Typography className={classes.instructions}>
Saved Successfully!
</Typography>
<Button
onClick={handleReset}
>
Reset
</Button>
</div>
) : (
<div>
<Button
variant="contained"
color="secondary"
disabled={activeStep === 0}
onClick={handleBack}
>
Back
</Button>
<Button
variant="contained"
color="primary"
// onClick={handleNext}
value={value}
onClick={handleChange}
>
{/* Continue */}
{activeStep === steps.length - 1 ? "Save & Update" : "Next"}
</Button>
</div>
)}
</Grid>
}
RadioButton checked field is not working for [No] by default .I had implemented it to set default as No and disable it and for Yes to update the fields
By default its coming unchecked for the both fields if i refresh the page.
I need to make it default for "NO"
Tried to fix the issue in various methods and ways but it's not fixing. I am not able to know why it's getting an error I don't understand the exact issue in the code. Could anyone help with the solution?
if i click Yes the user fields should be editable
code:
import React from "react";
import {
Box,
Typography,
Grid,
Link,
FormLabel,
RadioGroup,
Radio,
FormControlLabel,
} from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import { TextField, CurrencyTxtField } from "components/core";
const useStyles = makeStyles(() => ({
dinline: {
display: "inline",
},
fieldproductTester: {
fontWeight: 700,
},
}));
const ProductTester = ({
errors,
values,
handleChange,
handleBlur,
refProp,
}) => {
const classes = useStyles();
return (
<div ref={refProp}>
<FormLabel color="secondary" component="legend" mb={2}>
<Typography variant="h4" component="h4">
Testers
</Typography>
</FormLabel>
<Box pt={2}>
<Grid container spacing={1}>
<Grid item xs={12}>
<Typography component="div" color="textPrimary">
Would you like to give your customers the option to purchase a
tester of this product?if so,please include information about the
tester in the product description.
</Typography>
</Grid>
<Grid item xs={8}>
<RadioGroup
className={classes.dinline}
aria-label="tester"
name="tester"
value={values.tester}
onChange={handleChange}
disabled={!values.tester}
>
<FormControlLabel value="Yes" control={<Radio />} label="Yes"/>
<FormControlLabel
value="No"
control={<Radio />}
label="No"
enabled={values.tester === "No"}
/>
</RadioGroup>
</Grid>
{values.tester && (
<>
<Grid item xs={12}>
<Typography
variant="inherit"
className={classes.fieldproductTester}
>
Tester Price
</Typography>
</Grid>
<Grid item xs={8}>
<CurrencyTxtField
id="testerPrice"
name="testerPrice"
label=" "
variant="outlined"
value={values.testerPrice}
currencySymbol="$"
outputFormat="number"
digitGroupSeparator=""
textAlign="left"
onChange={handleChange}
onBlur={handleBlur}
error={!!errors.testerPrice}
helperText={errors.testerPrice ? errors.testerPrice : ""}
disabled={values.tester === "No"}
/>
</Grid>
<Grid item xs={12}>
<Typography
variant="inherit"
className={classes.fieldproductTester}
>
Tester SKU
</Typography>
</Grid>
<Grid item xs={8}>
<TextField
id="productSku"
name="sku"
label=""
ariaLabel="SKU"
value={values.sku}
disabled={values.tester === "No"}
/>
</Grid>
</>
)}
</Grid>
</Box>
</div>
);
};
export default ProductTester;
I've tested the following configuration - it works as expected. "No" is selected as a default value. Try to use this code as a reference point and then add all additional functionality step by step to see when it stops working.
<RadioGroup
aria-label="tester"
name="tester"
defaultValue="No">
<FormControlLabel
value="Yes"
control={<Radio />}
label="Yes"/>
<FormControlLabel
value="No"
control={<Radio />}
label="No"/>
</RadioGroup>
I am creating application for my school project and I am trying to use material ui in my application.
I am following official documentation through the website.
Here's the link I am following the Code.
I want to load new component when I click on the tab but i want the same navigation on the top so i can navigate to other pages.
here is the code I have been trying.
<div className={classes.root}>
<AppBar position="static" color="default">
<Tabs
value={value}
onChange={handleChange}
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
centered="true"
>
<Tab label="Dashboard" {...a11yProps(0)} />
<Tab label="User Manager" {...a11yProps(1)} />
<Tab label="Spot Manager" {...a11yProps(2)} />
<Tab label="Statistics" {...a11yProps(3)} />
<Tab label="Account Manager" {...a11yProps(4)} />
<Tab label="Log Out" {...a11yProps(5)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}></TabPanel>
<TabPanel value={value} index={1}>
<Dashboard />{" "}
</TabPanel>
My dashboard is just empty component like this
<>
<NavBar />
<h1>Hi</h1>
</>
here is how it just gets loading
after a while it shows kill page or wait
can anyone help me please ?
just write simple code as I learend,
<>
<AppBar position="static" color="default">
<Tabs>
<Tab label="Dashboard" />
<Tab label="User Manager" />
<Tab label="Spot Manager" />
<Tab label="Statistics" />
<Tab label="Finance" />
<Tab label="Log Out" />
</Tabs>
</AppBar>
**{value === 0 && <Dashboard />}
{value === 1 && <UserManager />}
{value === 2 && <SpotManager />}
{value === 3 && <Statistics />}
{value === 4 && <Finance />}**
</>
this highlighted Part will do the job,
Remember Tabs have index by themselves so don't worry like i didn's specify id or value how it will work.
You just match the index and load component you want to.
If you want to apply style, read documentation or watch youtube Modify for example,
<Tabs value={value}
onChange={handleChange}
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
>
///Your <Tab label="example /> goes here
</Tabs>
//index condition goes here to show components.
I'm struggling with this for a while now, I'm building a page so the user can create forms dynamically I have one react component that creates the forms and one that renders it, I'm currently facing problems with editing the forms already created.
const GigApplicationRenderer = (props) => {
const {
questions,
onSelectDelete,
onSelectEdit,
classes,
theme,
handleClickOpen,
handleClose,
open
} = props;
return (
<Fragment>
{questions.map((element, index) => (
<div className={classes.li} key={element.title}>
<Grid container spacing={24}>
<Grid item xs={12}>
{element.type === 'input' ? (
<Paper index={index} className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
<TextField
className={classes.textField}
value=""
label="answer text"
margin="normal"
/>
</Paper>
) : element.type === 'radiobox' ? (
<Paper className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
{element.options.map(option => (
<ListItem key={option} className={classes.itemsList}>
<RadioGroup>
<FormControlLabel
label={option}
value={option}
control={<Radio color="primary" />}
/>
</RadioGroup>
</ListItem>
))}
</Paper>
) : element.type === 'checkbox' ? (
<Paper className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
{element.options.map(option => (
<ListItem key={option} className={classes.itemsList}>
<FormControlLabel
label={option}
value={option}
control={<Checkbox checked={false} color="primary" />}
/>
</ListItem>
))}
<Divider light />
</Paper>
) : null}
</Grid>
</Grid>
</div>
))}
</Fragment>
);
};
this is the component that renders the code, it has some if statements that check the properties of the forms created and renders it accordingly.
this is the title component:
const Title = (props) => {
const {
element, onSelectDelete, onSelectEdit, index, handleClose, open
} = props;
return (
<Grid container spacing={24}>
{console.log(element.title)}
<Grid item xs={12} sm={9}>
<Typography style={{ textAlign: 'left' }} variant="subheading" gutterBottom>
{element.title}
</Typography>
</Grid>
<Grid item xs={12} sm={3}>
<Tooltip enterDelay={100} leaveDelay={100} placement="bottom" title="Edit">
<IconButton onClick={onSelectEdit(element, index)} aria-label="Edit">
<EditIcon />
</IconButton>
</Tooltip>
<Tooltip enterDelay={100} leaveDelay={100} placement="bottom" title="Delete">
<IconButton aria-label="Delete">
<DeleteIcon onClick={onSelectDelete(element)} />
</IconButton>
</Tooltip>
</Grid>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">
blabla
</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send updates
occasionally.
</DialogContentText>
<TextField
autoFocus
// value={element.title}
margin="dense"
label="question title"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</Grid>
);
};
I want it to open a dialog with the values of the element clicked so the user could edit it, the problem is that no matter which button was clicked, on the dialog, it always renders the last element of the form.
On the function onSelectEdit though, I get the correct element, I think it is happening because of the if statements of the first component.
the questions array look like this:
questions: [
{
title: 'Why do you want this job?',
type: 'input'
},
{
title: 'Do you know Javascript?',
type: 'radiobox',
options: ['yes', 'no']
},
{
title: 'What techs your know?',
type: 'checkbox',
options: ['html', 'css']
}
],
is there a way to render the correct element when the dialog opens?
I'm also open to any suggestion on how to accomplish this.