ReactJS Material UI disable other tabs on button click [closed] - reactjs

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 19 days ago.
Improve this question
Have similar code with action for a Button component click in each tab
https://codesandbox.io/embed/cbn97?codemirror=1
How can I disable other tabs on Button click in current tab?
How can I pass a "disabled" property to already displayed, rendered tab component, update it?
New to ReactJS

Since you've indicated in the comments that the current page may also be disabled I suggest you do something like this:
export default function SimpleTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const [isLoading, setIsLoading] = React.useState(false)
const handleOperation = () => {
setIsLoading(true)
// Do some synchronous operation that takes time
setIsLoading(false)
}
const handleChange = (event, 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)} disabled={isLoading}/>
<Tab label="Item Two" {...a11yProps(1)} disabled={isLoading}/>
<Tab label="Item Three" {...a11yProps(2)} disabled={isLoading}/>
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<button onClick={handleOperation}>start operation</button>
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
);
}
So the approach above is to create an isLoading state that identifies whether one of your tab button operations is in progress. Inside your tab button handler function(s) set isLoading to true making the tabs disabled and set isLoading to false after the operation is done.

Just put result of functions with conditions to disabled prop of your tabs:
export default function SimpleTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const [operationDone, setOperationDone] = React.useState(false)
const handleChange = (event, newValue) => {
setValue(newValue);
};
const isDisabled = (tabIndex) => {
if(operationDone) {
return false;
}
else {
if(value !== tabIndex) {
return true;
}
return false;
}
}
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value} onChange={handleChange} aria-label="simple tabs example">
<Tab label="Item One" disabled={isDisabled(0)} {...a11yProps(0)} />
<Tab label="Item Two" disabled={isDisabled(1)} {...a11yProps(1)} />
<Tab label="Item Three" disabled={isDisabled(2)} {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<button onClick={() => setOperationDone(true)}>change operation done</button>
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
);
}

Related

How to pass a value from reactjs app to another reactjs app?

I have to 2 Reactjs App, I need to pass a value from my App1 to App2 using link, but I dont know how, please help me thanks.
const location = useLocation();
const tab = getUrlParameter(location.search, 'tab');
with this I am now successfully getting the data in my App1 , lets says that data is (2), the problem is when i tried to click the other tab, it doesnt work now, why?
App1
<u>View Student</u> // I need to pass a value to App2, the value i need to pass is
App2 / receive value from App1
export default function BasicTabs() {
const location = useLocation();
const tab = getUrlParameter(location.search, 'tab'); // with this I am now successfully getting the data in my App1 , lets says that data is (2)
const [value, setValue] = React.useState(0);
useEffect(() => {
if(tab !== 2 ? tab : value){
console.log(tab)
setValue(2)
}else{
setValue(0)
}
})
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Box sx={{ width: '100%' }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={value} onChange={handleChange} aria-label="basic tabs example">
<Tab label="Item One" {...a11yProps(0)} />
<Tab label="Item Two" {...a11yProps(1)} />
<Tab label="Item Three" {...a11yProps(2)} />
</Tabs>
</Box>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</Box>
);
}
One option is to use query string parameters. So you would do something like
https://App2Url/student/4?App1Key=App1Value

How can I center the scrollable tab?

There are 3 tabs and I could not center them on the screen. How can I center the scrollable tab? As of now, it will only be on the left side of the screen
codesandbox: https://codesandbox.io/s/material-demo-forked-dbcxl?file=/demo.js
Below are the codes:
import * as React from "react";
import Tabs from "#mui/material/Tabs";
import Tab from "#mui/material/Tab";
import Box from "#mui/material/Box";
export default function ScrollableTabsButtonAuto() {
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
centered
>
<Tab label="Item One" />
<Tab label="Item Two" />
<Tab label="Item Three" />
</Tabs>
);
}
It is because the container of the Tabs has the same width as the Tabs.
You should be able to wrap the Tabs component with a Box which has full width.
For example,
<Box display="flex" justifyContent="center" width="100%">
<Tabs ...>
...
</Tabs>
</Box>

How to change tab from parent in react material Tabs

I've got a component like FeedSwitcher with two tabs inside
one for the general feed the other one only for the posts of the current user
in FeedSwitcher component at the start the value is 0 therefore
the current user can view all the feed.
const FeedSwitcher = ({feed, posts, user }: FeedSwitcherProps) => {
const classes = useStyles();
const [value, setValue] = useState(0);
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<Tabs
value={value}
onChange={handleChange}
variant="fullWidth"
indicatorColor="primary"
textColor="primary"
aria-label="switcher tabs"
>
<Tab icon={<PeopleIcon />} aria-label="phone" />
<Tab icon={<PersonIcon />} aria-label="favorite" />
</Tabs>
<TabPanel value={value} index={0}>
<Feed feed={feed} />
</TabPanel>
<TabPanel value={value} index={1}>
<Posts posts={posts} user={user} />
</TabPanel>
</div>
);
};
After the current user post a new thread
(the form is in the parent component)
I want to show the tab with index 1
How can set the value from the parent?
Should I use a redux state or is there
an other direct and simpler way?
The state needs to be in the parent component.
You can feed the child component with the value, and pass it a function argument like onValueChange that it can use to trigger an update on the parent's state.
// in parent
const [feedSwitcherValue, setFeedSwitcherValue] = useState(0);
return (
<FeedSwitcher
feed={feed}
posts={posts}
user={user}
value={feedSwitcherValue}
onValueChange={value => setFeedSwitcherValue(value)}
/>
);
// child
const FeedSwitcher = ({feed, posts, user, value, onValueChange }: FeedSwitcherProps) => {
const classes = useStyles();
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
onValueChange(newValue);
};
return (
<div className={classes.root}>
<Tabs
value={value}
onChange={handleChange}
variant="fullWidth"
indicatorColor="primary"
textColor="primary"
aria-label="switcher tabs"
>
<Tab icon={<PeopleIcon />} aria-label="phone" />
<Tab icon={<PersonIcon />} aria-label="favorite" />
</Tabs>
<TabPanel value={value} index={0}>
<Feed feed={feed} />
</TabPanel>
<TabPanel value={value} index={1}>
<Posts posts={posts} user={user} />
</TabPanel>
</div>
);
};

React Material UI - Tabs - How to disable lazy loading of tabs?

I am creating some react tabs based off of the example shown here for Material UI: https://material-ui.com/components/tabs/.
The problem I am encountering is that my tabs are lazy loading the linegraph components instead of performing all the queries on initial page load. Does anyone have some suggestions of where I can optimize this to make each tab load immediately on page load?
function TabPanel(props) {
const { children, value, index} = props;
return (
<Typography>
{value === index && <Box p={3}>{children}</Box>}
</Typography>
);
}
class SimpleTabs extends Component {
constructor(props) {
super(props)
console.log(props.color)
this.state = {
value: 0
};
}
handleChange = (event, newValue) => {
this.setState({value: newValue});
};
render() {
return (
<div>
<AppBar position="static">
<Tabs value={this.state.value} onChange={this.handleChange}>
<Tab label="Item One"/>
<Tab label="Item Two"/>
<Tab label="Item Three"/>
</Tabs>
</AppBar>
<TabPanel value={this.state.value} index={0}>
<LineGraph className={styles.graphBox} name={"Guest Count"} url={'http://127.0.0.1:5000/***/***'} initialFilterData={this.props.initialFilterData} filterData={this.props.filterData}/>
</TabPanel>
<TabPanel value={this.state.value} index={1}>
<LineGraph className={styles.graphBox} name={"Total Sales"} url={'http://127.0.0.1:5000/***/***'} initialFilterData={this.props.initialFilterData} filterData={this.props.filterData}/>
</TabPanel>
<TabPanel value={this.state.value} index={2}>
<LineGraph className={styles.graphBox} name={"Avg Check Size"} url={'http://127.0.0.1:5000/***/***'} initialFilterData={this.props.initialFilterData} filterData={this.props.filterData}/>
</TabPanel>
</div>
)}
}
export default SimpleTabs;
Add hidden={value !== index} to the Typography in TabPanel and remove the value === index && condition inside the Typography so that the children of all the tab panels are rendered immediately but hidden (except for the currently selected one).
Example:
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<Typography
component="div"
role="tabpanel"
hidden={value !== index}
{...other}
>
<Box p={3}>{children}</Box>
</Typography>
);
}

How to show contents inside a tab?

I am trying to create a form with three tabs.Now the tabs are created and i am able to switch between them but can not figure out how to display contents inside a tab
I have tried writing markup tags like h1 in between but nothing is shown on the output.
export class Stackreact extends Component {
constructor(props) {
super(props);
this.state = { value: '1' }
}
handle_change = (value) => {
this.setState({ value })
}
render() {
return (
<div>
<Tabs value={this.state.value} onChange={(e, v) => { this.handle_change(v) }} indicatorColor="primary"
textColor="primary" centered>
<Tab value='1' label='BASIC DETAILS'><h1>First Tab</h1></Tab>
<Tab value='2' label='CONTACT DETAILS'><h1>Second Tab</h1></Tab>
<Tab value='3' label='MORE DETAILS'><h1>Third tab</h1></Tab>
</Tabs>
</div>
)
}
}
I want the contents of h1 tags to be displayed in their respective tabs. Please help.Also i am new to this language.
After working a lot I have come up with this solution which is working fine.
render() {
let content_array = [<h1>First Tab</h1>, <h1>Second Tab</h1>, <h1>Third Tab</h1>];
return (
<div>
<Tabs value={this.state.value} onChange={(e, v) => { this.handle_change(v) }} indicatorColor="primary"
textColor="primary" centered>
<Tab value='1' label='BASIC DETAILS'></Tab>
<Tab value='2' label='CONTACT DETAILS'></Tab>
<Tab value='3' label='MORE DETAILS'></Tab>
</Tabs>
<Paper>
{content_array[this.state.value - 1]}
</Paper>
</div>
)
}
You can try using TabView and TabPanel from primereact
<TabView>
<TabPanel>
<h1>First Tab</h1>
<TabPanel />
<TabPanel>
<h1>Second Tab</h1>
<TabPanel />
<TabView />
You can research on your own on the props accepted by TabView and TabPanel
you can use components like this:
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value} onChange={handleChange} aria-label="simple tabs example">
<Tab label="Item One" {...a11yProps(0)} />
<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>
official link : Tabs
You are trying to see the content but you've defined it in the wrong place, here you have an example of how to use Tabs and Tab, because you need to define the data that you want inside of each Tab outside the Tabs component (Tab in meant to be used as a self-closing tag).
Here is the simplest answer using hooks inspired by the accepted answer.
import { useState } from 'react';
..
const [tabState, setTabState] = useState(1);
...
const handleTabs = (value) => {
setTabState(value);
return;
}
let tabs_array = [<>{variable_with_contents_tab_1}</>, <>{tab_2_contents}</>];
Then in the render, you can provide the tab ui
<Paper className={classes.root}>
<Tabs
value={tabState}
onChange={(event, value) => { handleTabs(value) }}
indicatorColor="primary"
textColor="primary"
centered
>
<Tab value={1} label='Tab1'>
</Tab>
<Tab value={2} label="Tab2" />
</Tabs>
</Paper>
<Paper>
{tabs_array[tabState-1]}
</Paper>

Resources