Dynamically adding a new object to an array will result in a new <Tab>.
The arrows don't show, but after scrolling to the left they appear.
render() {
const tabs = this.grids.map((grid) => <Tab key={grid.gridIndex} />);
return (
<div>
<Tabs scrollable scrolling="on">
{tabs}
</Tabs>
</div>
)
}
Any idea what's wrong?
In reviewing the code base, there are currently 3 "events" which cause an evaluation of the scroll button visibility state:
componentDidMount)There is no handler for a change in the number of child tabs as that wasn't a use case I had originally anticipated. It's likely a trivial change within componentDidUpdate to see if the child tabs have been mutated and then evaluate to determine if the scroll button visibility state needs to be updated.
I'll see if I can work something up and get a PR in for it.
As I think this through, there are a number of things that one could do to a <Tab> child which might cause the scroll buttons to require a change to visibility state. Effectively, any mutation which might change the scrollWidth of the <Tabs> container could mean that the visibility state needs update. For instance, a change to the text or font size of a tab's label could potentially introduce that. Therefore, it can't simply be a check of the number of tab children in order to have a complete solution.
It's likely a trivial change within componentDidUpdate to see if the child tabs have been mutated
I think it will actually be more straightforward and reduce the risk of missing any use cases if I simply add an unconditional call to updateScrollButtonState to componentDidUpdate. That function has a decent level of conditional logic to reduce any performance impact caused by the extra calls.
Prueba as铆:
const tabs = this.grids.map((grid) => { return ( <Tab key={grid.gridIndex} /> ) });
Hey, I made a small gist which might be helpful to as a starter template: https://gist.github.com/Rahul-RB/273dbb24faf411fa6cc37488e1af2415
The same thing is pasted here for quick reference:
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:
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);
Most helpful comment
In reviewing the code base, there are currently 3 "events" which cause an evaluation of the scroll button visibility state:
componentDidMount)There is no handler for a change in the number of child tabs as that wasn't a use case I had originally anticipated. It's likely a trivial change within
componentDidUpdateto see if the child tabs have been mutated and then evaluate to determine if the scroll button visibility state needs to be updated.I'll see if I can work something up and get a PR in for it.