Create custom TabPane using react-bootstrap - javascript

I would create custom Tab Form from JSON, using React and boostrap. Using this function my code work correctly.
function DisplayForm(props) {
return(
<div className="row">
<Tabs className="mb-3">
{Array.from(new Map(Object.entries(json))).map((data) => (
<Tab eventKey={data[0]} title={data[0]}> </Tab>
))}
</Tabs>
</div>
);
}
}
data[0] is the tabName.
Now, I would create custom tab, based on json value. For example, something, like this:
function DisplayCustomTab(props) {
return(
<div className="row">
<TabContainer className="mb-3">
<TabContent>
{Array.from(new Map(Object.entries(json))).map((data) => (
<>
{(() => {
if(myCondition ) {
return(
<>
<CreateTAB data={data[0]} />
</>
)
}
})()}
</>
))}
</TabContent>
</TabContainer>
</div>
);
}
function CreateTAB(props) {
console.log("tab name: " + props.data); // this line works
return(
<TabPane eventKey={props.data} title={props.data}> </TabPane>
);
}
I using TabPane, TabContent and TabContainer because using Tab and Tabs I get following error:
component is not meant to be rendered! It's an abstract component that is only valid as a direct Child of the `Tabs` Component. For custom tabs components use TabPane and TabsContainer directly
Anyone can explain where I'm wrong? Thank you

Related

React table rowProps prop doesnt log anything

[Basically, we're using this from one of our libraries. But the thing is while using it through our package the rowProps prop doesn't work]
(https://i.stack.imgur.com/fER2B.png).
import { AdvancedTable } from "ims-ui-kit";
function Table(props) {
console.log(props)
return <AdvancedTable {...props} />;
}
export default Table;
Here is another screenshot of the prop passing through the table we are using. It doesn't log anything.
[enter image description here]
<>
{alert}
<div className="content">
<ReactTable
// hasBulkActions={true}
data={data}
filterable
{...rest}
resizable={false}
columns={columns.slice()}
defaultPageSize={10}
showPaginationTop
showPaginationBottom={false}
className="-striped -highlight"
rowProps={(row) => {
onclick = () => {
console.log("hello", row);
};
}}
/>
<Modal title="Risk management">
<RiskDetail isModalOpen={isOpen} />
</Modal>
</div>
</>

map function not rendering in react jsx

I am new to react and was trying to use a map function inside jsx to render an array. However nothing gets rendered inside the loop .
I am passing data to my child component like this:
{showMaterialConfirmModal && (
<MaterialModalConfirm
closeModal={setshowMaterialConfirmModal}
orderList={orderListE}
itemList={itemListE}
errorList={errorListE}
title="Success"
/>
)}
and inside the child component I am calling the map function like this:
<Card>
<GridContainer>
<GridItem xs={12}>Design Successful for: 0</GridItem>
<h5>Order:{props.orderList[0]}</h5>
{props.orderList.map((order, i) => {
<div>
{order}
<h1>Hi</h1>
{/* <GridItem xs={12}>
order/item no {order[i]}/{props.itemList[i]} due to{" "}
{props.errorList[i]}
</GridItem> */}
</div>;
})}
</GridContainer>
</Card>
The data in orderList is coming in the tag however nothing gets printed which is inside the loop.
I have checked various documents to run the map function however I am at a loss as to why nothing is getting printed .
Please help
I think you are missing a return here:
{props.orderList.map((order, i) => {
return (
<div>
{order}
<h1>Hi</h1>
</div>);
})}
or
{props.orderList.map((order, i) => (
<div>
{order}
<h1>Hi</h1>
</div>
))
}

How to share one dialog window for loading different data across multiple child components

I am in the process of learning react, and converting all my classes into functional components with hooks.
I have a main dashboard that shows a list of tiles/cards, and each card is able to bring up the same dialog window for editing but with different data.
The way I have achieved this currently is that I have a component that maps an array of items and each item have a child card component with its own dialog window. I was wondering if it is possible to reuse a common dialog window component by passing different data upon opening the window so it can be shared.
Parent component
public render() {
return(
<div>
{/* Opens the same edit window for creating new workout */}
<AddWorkoutButton updateWorkout={this.updateWorkouts} isDarkMode={this.props.isDarkMode}/>
<div className="container" style={{paddingBottom: '3rem'}}>
<div className="row">
{/* Create individual card for each workout */}
{this.state.workoutData.map((workoutData: object, index: number) =>
<div className="col-md-6 col-lg-4" key={index}>
{/* Create each card as child component */}
<WorkoutCard workoutData={workoutData} updateWorkout={this.updateWorkouts} isDarkMode={this.props.isDarkMode}/>
</div>
)}
</div>
</div>
</div>
);
}
Child component (Card)
public render() {
return(
<div>
{/* Inside edit window contains a dialog component */}
<EditWindow
openEditWindow={this.state.openEditWindow}
handleClose={this.handleClose}
updateWorkout={this.props.updateWorkout}
isDarkMode={this.props.isDarkMode}
workoutData={this.props.workoutData}
/>
<Card className={classes.card}>
...
<Card/>
</div>
)
}
Edit window (dialog component that I wish to share instead of generating for each child component)
Note: this component I have converted to a functional component with hooks (not sure if that affects anything)
return (
<div>
{/* parent components will invoke the edit window/dialog */}
<Dialog
maxWidth={"md"}
fullWidth
open={props.openEditWindow}
// onEnter={openWorkoutDialog}
TransitionComponent={Transition}
onClose={() => {setWorkoutData(props.workoutData); props.handleClose()}}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
...
</Dialog>
Finally, with react dev tools we can see that each workout card has its own edit window
You can move the EditWindow component inside of you parent to achieve what you want. Then you can have state in you parent component that holds the workoutData that should be edited in the modal.
class Parent extends React.Component {
state = {
workoutData: null
};
render() {
return (
<div>
<AddWorkoutButton
updateWorkout={this.updateWorkouts}
isDarkMode={this.props.isDarkMode}
/>
<div className="container" style={{ paddingBottom: "3rem" }}>
<div className="row">
{/* Create individual card for each workout */}
{this.state.workoutData.map(
(workoutData: object, index: number) => (
<div className="col-md-6 col-lg-4" key={index}>
{/* Create each card as child component */}
<WorkoutCard
workoutData={workoutData}
updateWorkout={this.updateWorkouts}
isDarkMode={this.props.isDarkMode}
editWorkoutData={() =>
this.setState({ workoutData: workoutData })
}
/>
</div>
)
)}
</div>
<EditWindow
openEditWindow={this.state.workoutData !== null}
handleClose={() => this.setState({ workoutData: null })}
updateWorkout={this.props.updateWorkout}
isDarkMode={this.props.isDarkMode}
workoutData={this.state.workoutData}
/>
</div>
</div>
);
}
}
class WorkoutCard extends React.Component {
render() {
return (
<div>
<Card className={classes.card} onClick={this.props.editWorkoutData}>...</Card>
</div>
);
}
}
function EditWindow(props) {
return (
<div>
<Dialog
maxWidth={"md"}
fullWidth
open={props.openEditWindow}
// onEnter={openWorkoutDialog}
TransitionComponent={Transition}
onClose={() => {
setWorkoutData(props.workoutData);
props.handleClose();
}}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
...
</Dialog>
</div>
);
}
Well a simple approach would be to use a Dialog component that renders itself into the parent "root" of your application with a react-portal. This Dialog might update whenever the parent that manages your cards is updating its state giving some configuration like "open", "text", "heading" etc. to the Dialog component via props.
Take a look at this solution: https://blog.bitsrc.io/build-a-simple-modal-component-with-react-16decdc111a6

Open popup on DataTable row click in ReactJS

I'm using reactjs-popup and react-data-table-component npm libraries and I want to open a pop-up window when a row is clicked.
This is my code:
onRowClicked = (rowData,e) => {
return (<Popup
trigger={/*e.target.value*/}
modal>
{
close => (
<div>
// some code
</div>
)
}
</Popup>)
}
render() {
return (
<DataTable
title={title}
columns={columns}
data={data}
highlightOnHover={true}
pointerOnHover={true}
onRowClicked={this.onRowClicked}
noDataComponent='No content'
/>
)
}
Is it possible to bind the trigger attribute of Popup to the clicked row?
One Naive way to do this would be by putting the table details in the pop trigger
for instance
render() {
let SongList = this.state.Songs.map(({Artist,Title, Album, Id}, index) => {
return (
<Popup modal trigger={<tr key={Id} >
<td>{index+1}</td>
<td>{Artist}</td>
<td>{Title}</td>
<td>{Album}</td>
</tr>}>
{close => <Content4 close={close} />}
</Popup>
);
});
return(
<>
{SongList}
</>
);
}
It works but it is not the most neat or optimal code

multiple items inside the rightIconButton of a MaterialUI ListItem

I want to attach multiple items to the rightIconButton inside a ListItem.
I'm using Material UI v0.20 and React#15.6.2
<ListItem
rightIconButton={
<span>
<RaisedButton />
<TrashIcon />
</span>
}
/>
How can i wrap the items to avoid the warning?
Warning: Unknown prop onKeyboardFocus on span tag. Remove this prop from the element.
Try using HOC:
function Single() {
return (
<div>
<RaisedButton>Hello</RaisedButton>
<RaisedButton>wORLD</RaisedButton>
</div>
);
}
function App() {
return (
<MuiThemeProvider>
<List>
<ListItem rightIconButton={<Single />} />
</List>
</MuiThemeProvider>
);
}
A custom component will help to remove the warning:
function GroupedButtons(props) {
return (
<span>
<RaisedButton>Hello</RaisedButton>
<RaisedButton>WORLD</RaisedButton>
</span>
)
}
...
function App() {
...
<ListItem
rightIconButton={
<GroupedButtons />
}
/>
Working example:

Categories

Resources