Skip to content

Instantly share code, notes, and snippets.

@Rahul-RB
Last active March 26, 2024 15:03
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save Rahul-RB/273dbb24faf411fa6cc37488e1af2415 to your computer and use it in GitHub Desktop.
Save Rahul-RB/273dbb24faf411fa6cc37488e1af2415 to your computer and use it in GitHub Desktop.
Dynamically add and remove tabs in Material UI (Browser tabs feature)
/* No licenses, use as pleased.
* The code here uses React Class components (ES6 classes).
* Ken Nguyen has made a hooks version of this! Please find that here: https://codesandbox.io/s/addanddelete-tabs-mui-bo7tw
* Cheers!
*/
import React, { Component } from "react";
import {
withStyles,
AppBar,
Tabs,
Tab,
Grid,
Button
} from "@material-ui/core";
import Add from "@material-ui/icons/Add";
import Close from "@material-ui/icons/Close";
import cloneDeep from "lodash/cloneDeep";
const styles = theme => ({
root: {
flexGrow: 1,
marginTop:"60px",
width: "100%",
backgroundColor: theme.palette.background.paper
},
appBar:{
color:"inherit",
backgroundColor: theme.palette.background.paper
}
});
class CustomTabs extends Component {
constructor(...args){
super(...args);
this.state = {
value: 0,
tabList : [{
key:0,
id:0,
}]
};
}
addTab = () => {
this.setState((state,props)=>{
let tabList = cloneDeep(state.tabList);
let id = tabList[tabList.length-1].id+1;
tabList.push({
key:id,
id:id,
});
return {
tabList,
}
})
}
deleteTab = (e) => {
// prevent MaterialUI from switching tabs
e.stopPropagation();
// Cases:
// Case 1: Single tab.
// Case 2: Tab on which it's pressed to delete.
// Case 3: Tab on which it's pressed but it's the first tab
// Case 4: Rest all cases.
// Also cleanup data pertaining to tab.
// Case 1:
if(this.state.tabList.length === 1){
return; // If you want all tabs to be deleted, then don't check for this case.
}
// Case 2,3,4:
let tabID = parseInt(e.target.id);
let tabIDIndex = 0;
let tabList = this.state.tabList.filter((value,index)=>{
if(value.id === tabID){
tabIDIndex = index;
}
return value.id !== tabID;
});
this.setState((state,props)=>{
let curValue = parseInt(state.value);
if(curValue === tabID){
// Case 3:
if(tabIDIndex === 0){
curValue = state.tabList[tabIDIndex+1].id
}
// Case 2:
else{
curValue = state.tabList[tabIDIndex-1].id
}
}
return {
value:curValue
}
},()=>{
this.setState({
tabList:tabList
})
});
}
handleTabChange = (event, value) => {
this.setState({ value });
}
render() {
const { classes } = this.props;
const { value } = this.state;
// console.log(this.state);
return (
<AppBar position="static" className={classes.appBar}>
<Grid
container
alignItems="center"
justify="center"
>
<Grid
item
xl={11}
lg={11}
md={11}
sm={11}
xs={11}
>
<Tabs
value={value}
onChange={this.handleTabChange}
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
>
{
this.state.tabList.map((tab)=>(
<Tab
key={tab.key.toString()}
value={tab.id}
label={"Node "+tab.id}
icon={
<Close
id={tab.id}
onClick={
this.deleteTab
}
/>
}
className="mytab"
/>
))
}
</Tabs>
</Grid>
<Grid
item
xl={1}
lg={1}
md={1}
sm={1}
xs={1}
>
<Button
variant="outlined"
onClick={this.addTab}
>
<Add/>
</Button>
</Grid>
</Grid>
</AppBar>
);
}
}
export default withStyles(styles)(CustomTabs);
@yadavendra15
Copy link

Sure Rahul,
Thanks for it

@yadavendra15
Copy link

Hey @Rahul-RB ,

Can you Please help me in https://codesandbox.io/s/thirsty-joliot-pjhkd?file=/src/AddAndDeleteTab.js

actually, I want to add a Whiteboard in those tabs..
Now, I'm stuck at one point..

When I draw something in the whiteboard and switch the tabs, then my tabpanel re-renders, but I don't want to do so. I want to avoid the re-render of tabpanel.

And my second issue is, Suppose I draw something on WhiteBoard1 and I close that tab 1.. then, that content will be shifted to the next tab, and shows as the content of tab 2..

Please help me in this..

@smarajitWOW
Copy link

Can the tabs be renamed?

@pereiraryan
Copy link

hey @Rahul-RB do we have an example where there are contents to these tabs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment