how to have multiple cards in each Carousel slide react-bootstrap - javascript

I'm working with react-bootstrap and I have my data coming from an API and saved in recipes as an array.
I'm trying to have Carousel with react-bootstrap but right now it shows each item on a separate slide, how can I show 3 items on each slide?
this is my code
<div>
<Wrapper>
<h3>Breakfast Recipes</h3>
<Carousel>
{recipes.map((item,index) => (
<Carousel.Item key={index}>
<Card style={{ width: '18rem' }}>
<Card.Img variant="top" src={item.photo_location} />
<Card.Body>
<Card.Title>{item.name}</Card.Title>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
</Carousel.Item>
))}
</Carousel>
</Wrapper>
</div>
I know that to do so I should have 3 <Carousel.Item> tags but I can't figure out how to do it with map

Assuming that the goal is to have 3 cards on each slide, it seems that instead of having 3 <Carousel.Item>, the desired output should probably be to have each <Carousel.Item> containing 3 <Card>.
Perhaps try use reduce on recipes to make an array that groups every 3 recipes to map a <Carousel.Item> for each group, and then nest another map inside to output 3 <Card>.
The below example also added a <div> to wrap the <Card> and place them horizontally. It used bootstrap syntax with assumption that the project also uses bootstrap classes.
But if inline styling is preferred, perhaps change <div className="d-flex justify-content-center"> to <div style={{display:"flex", justifyContent: "center"}}>.
Live demo of the example: stackblitz
A very basic example could be:
// Helper function to group every 3 recipe to a new array
const reduceRecipes = (acc, cur, index) => {
const groupIndex = Math.floor(index / 3);
if (!acc[groupIndex]) acc[groupIndex] = [];
acc[groupIndex].push(cur);
console.log(acc);
return acc;
};
return (
<div>
<Wrapper>
<h3>Breakfast Recipes</h3>
<Carousel>
{recipes.reduce(reduceRecipes, []).map((item, index) => (
<Carousel.Item key={index}>
<div className="d-flex justify-content-center">
{item.map((item, index) => {
return (
<Card key={index} style={{ width: "18rem" }}>
<Card.Img variant="top" src={item.photo_location} />
<Card.Body>
<Card.Title>{item.name}</Card.Title>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
);
})}
</div>
</Carousel.Item>
))}
</Carousel>
</Wrapper>
</div>
);
Some further custom styles should probably be added to make this work better, but hope that this still helps.

Related

React beautiful dnd first column of two not working properly - unable to find draggable with id

I've implemented react beautiful dnd into my app, however I've found that dragging items that are initialised in the first column mostly doesn't work (it sometimes works if you keep refreshing). I tried swapping my columns around and it appears the first one rendered has the problem rather than one column having an issue.
I'm not sure what is causing it, the error I receive in the console from the library is:
Unable to find draggable with id: 6112804b8127dd10b00138d8.
The id however matches the ids in my lists and the HTML viewed in inspect element.
Here's the minimum code, I've not included the functions for filtering search, reordering, move and onDragEnd (isn't being fired as it doesn't find the draggable)
const id2List = {
'available': availableSections,
'selected': selectedSections
};
const getList = id => id2List[id];
return (
<Container>
<Widget title={template.name} paddingStyle="10px" buttonRight={<SaveButton handleSubmit={handleSubmit} loading={loading}/>}>
<DragDropContext onDragEnd={onDragEnd}>
<Row>
<Col >
Available Sections
<Form.Control onChange={(e) => setSearchTextAvailable(e.target.value)} className="mb-3" type="text" placeholder="Search..." />
<Droppable key="available" droppableId="available">
{provided => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{Object.keys(visibleAvailableSections).map((section) => {return <SectionCard key ={visibleAvailableSections[section]._id} section={ visibleAvailableSections[section] } index={parseInt(availableSections.indexOf(visibleAvailableSections[section])) } /> })}
{provided.placeholder}
</div>
)}
</Droppable>
</Col>
<Col>
Selected Sections
<Form.Control onChange={(e) => setSearchTextSelected(e.target.value)} className="mb-3" type="text" placeholder="Search..." />
<Droppable key="selected" droppableId="selected">
{provided => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{Object.keys(visibleSelectedSections).map((section) => {return <SectionCard key ={visibleSelectedSections[section]._id.toString()} section={ visibleSelectedSections[section] } index={parseInt(selectedSections.indexOf(visibleSelectedSections[section])) } /> })}
{provided.placeholder}
</div>
)}
</Droppable>
</Col>
</Row>
</DragDropContext>
</Widget>
</Container>
)
const SectionCard = ({section, index}) => {
return (
<Draggable draggableId={section._id.toString()} key={section._id} index={index}>
{provided => (
<Card key={"card-" + section._id.toString()} style={{ width: '18rem' }}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Card.Body>
<Card.Title>{ section.name }</Card.Title>
<Card.Subtitle className="text-muted">{ section.description }</Card.Subtitle>
{ section.tags.map((tag) => {
return <Badge pill bg={"secondary"} key={section._id + tag} >{ tag }</Badge>
})}
</Card.Body>
</Card>
)}
</Draggable>
);
}

Why doesn't Next.js Json.map work properly?

I want to build a simple component where the data comes from a JSON list. On the website I can see the console.log(dat.CardId) so it works for just console.log(). I can't see the cards from the .map function. The Style is bootstrap. I really don't think that something is wrong at the code.
import { Card,Button,Container,Row,Col } from 'react-bootstrap'
const data = [{'CardTitle':'Simple Website','CardText':"Some quick example text to build on the card title and make up the bulk of the card's content.", "CardId":"Simple-Website"},{'CardTitle':'Simple Website','CardText':"Some quick example text to build on the card title and make up the bulk of the card's content.", "CardId":"Simple-Website"} ]
export default function Cards() {
return (
<>
<div>
<Container fluid>
Cards
{data.map(dat => {
{console.log(dat.CardId)}
<Row>
<Col>
<Card style={{ width: '18rem' }}>
<Card.Img variant="top" src="pexels-tima-miroshnichenko-6612358 (2).jpg/100px180" />
<Card.Body>
<Card.Title>{dat.CardTitle}</Card.Title>
<Card.Text>
{dat.CardText}
</Card.Text>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
</Col>
</Row>
})}
</Container>
</div>
</>
)
}
Use return ( ... ) in a .map to render an element. https://stackoverflow.com/a/39999745/15257712
Example:
array.map((entry, index) => {
return (
<div key={index}>
...
</div>
)
})

Is there a way to map over an array of objects in react and also get the accosiated images from cloudinary

I am trying to map over an array of objects in react, the object includes a product name and id. Im using cloudinary to store my images but im not sure what to put as the publicId
Im trying to get the public id associated with each object to pass into the public id
This is my code
<div>
<Container>
<h2>My Products</h2>
<CardDeck>
{myProducts.map((product) => (
<Card style={{ minWidth: "14rem" }}>
<Image cloudName='dgeizgzdw' publicId="equipped/{product._id}" className='card-img-top'/>
<Card.Body>
<Card.Title>{product.product}</Card.Title>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
))}
</CardDeck>
</Container>
</div>
It works when i hard code the product id like so.
<div>
<Container>
<h2>My Products</h2>
<CardDeck>
{myProducts.map((product) => (
<Card style={{ minWidth: "14rem" }}>
<Image cloudName='dgeizgzdw' publicId={'equipped/5f1fcbd42371c61758db2962'} className='card-img-top'/>
<Card.Body>
<Card.Title>{product.product}</Card.Title>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
))}
</CardDeck>
</Container>
</div>
);
Ive tried interpolating the public id the main issue is that the first part of the string 'equipped/ is not saved in the public id
Instead of:
<Image cloudName='dgeizgzdw' publicId="equipped/{product._id}" className='card-img-top'/>
write:
<Image cloudName='dgeizgzdw' publicId={`equipped/${product._id}`} className='card-img-top'/>

Array map function renders correct but calls function with last element rendered

I am using the map function to iterate through a JSON Array which looks similar to this
table=[
{"name":"jon snow",
"house":"stark"
},
{
"name":"arya",
"house":"stark"
},
{"name":"cersei",
"house":"lannister"
}
]
Map function renders the items perfectly however, the onClick handler seems to pass only the last item of the array.
For example, the text items are rendered to display the appropriate name, however, on clicking their individual action button seems to pass only the last element.
Here, after triggering the event handler "handleClose", I logged the "item" element printed to the console but it displays element with name "cersei" even on clicking the element with name "jon snow".
The syntax seems to be fine for the event handler for React afaik. And, since the variable "item" is also local variable within the function. It shouldn't display the last item in the array. Is there anything I am missing over here?
{/*Event Handler*/}
function handleClose(item) {
console.log(item)
setAnchorEl(null);
}
{/*Few lines of code after in the return function of React*/}
var table2=[
{"name":"jon snow",
"house":"stark"
},
{"name":"arya",
"house":"stark"
},
{"name":"cersei",
"house":"lannister"
}
]
console.log(table);
return(
<div>
<div>
</div>
{/*Actual table data*/}
<div>
<Card style={{width:'100%'}}>
<Card.Body>
<div >
{table2.map((item,index)=>{
let tempElement =item;
return(
<div >
<Grid container spacing={0}>
<Grid item xs={2} >
<div style={{backgroundColor:'#fff'}}>
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar src={item.picture} />
</ListItemAvatar>
<ListItemText style={{wordBreak:'normal'}}
primary={item.name}
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
className={classes.inline}
color="textPrimary"
>
{getRoleFromData(item.roles)}
</Typography>
</React.Fragment>
}
/>
</ListItem>
</div>
</Grid>
{/*View/Edit buttons */}
<Grid item xs style={{backgroundColor:'#fff'}} >
<div>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>Action</Button>
<ThemeProvider>
<Menu
id="simple-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem><Button onClick={()=>handleClose(item)}>View</Button></MenuItem>
<MenuItem><Button onClick={()=>handleClose(item)}>Edit</Button></MenuItem>
</Menu>
</ThemeProvider>
</div>
</Grid>
</Grid>
<div>
<Divider variant="inset"/>
</div>
</div>
);
})
}
</div>
</Card.Body>
</Card>
</div>
</div>

Click events are not available on the map of the react

{userList.map(v => (
<Card
key={v.user}
onClick={() =>
console.log("object")
}
>
<Card.Header
title={v.user}
thumb={require(`../img/${v[tableName].avatar}.png`)}
extra={<span>{v[tableName][extra]}</span>}
/>
<Card.Body>
{v[tableName].desc.split(/\n/g).map((v, k) => (
<li key={k}>{v}</li>
))}
</Card.Body>
</Card>
))}
Click events are not available on the .map() function in React
Card Component of React material UI does not support onClick props so you should not use it.
Quick Fix would be to enclose it inside a div and add onClick on the div as shown below:
<div onClick=> {() =>
console.log("object")
}>
<Card>
.....
</Card>
</div>
Or You can use some different library from :
https://material-ui.com/api/card-action-area/

Categories