Last active
March 26, 2024 15:03
-
-
Save Rahul-RB/273dbb24faf411fa6cc37488e1af2415 to your computer and use it in GitHub Desktop.
Dynamically add and remove tabs in Material UI (Browser tabs feature)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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); |
Sure Rahul,
Thanks for it
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..
Can the tabs be renamed?
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
@yadavendra15 thank you, could you please "star" this gist.
I remember @KenNguyen-0107 had created a hooks version of this here: https://codesandbox.io/s/addanddelete-tabs-mui-bo7tw
Could you try that and let me know if that works?