Get bootstrap modal close event in reactjs - reactjs

I am using React 16 with Bootstrap 4.
I am using bootstrap modal to display some values. I need to reset these values whenever modal is closed.
For Modal I have created a separate component. I dont want to use React-Modal as I get all the functionality in the current modal.
I know in plain javascript it is achieved using below code:
$(".modal").on("hidden.bs.modal"){
//reset values here
};
But I dont know how this is achieved in ReactJS?
Below is my code for modal:
<div className="modal fade modal-flex" id="large-Modal-OneUser" tabIndex={-1} role="dialog">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header" style={{display: 'block'}}>
<div className="row">
<div className="col-md-6">
<h2 style={{fontWeight:600}}>{newTimelineData.length > 0 ? newTimelineData[0].candidateName : ""}</h2>
</div>
<div className="col-md-6">
<span style={{display: 'inline-flex',alignItems: 'center',float:'right'}}><h4 style={{paddingRight:20}}>{isNotEmpty(this.state.scheduledFor) ? moment(this.state.scheduledFor).format("DD-MMM-YYYY"):this.checkScheduledFor(newTimelineData)}</h4>
<h3 style={{paddingRight: 10}}>{isNotEmpty(this.state.probability) ? this.getProbabilityHTML() : this.checkProbability(newTimelineData)}</h3>
{/*<button type="button" className="close" data-dismiss="modal" aria-label="Close" style={{marginTop: 0,marginBottom: 10}}>
<span aria-hidden="true">×</span>
</button>*/}
</span>
</div>
</div>
</div>
<div className="modal-body">
<div className="col-md-12">
{/*<div className="card">*/}
{/*<div className="card-block">*/}
{/* Horizontal Timeline start */}
<div className="cd-horizontal-timeline">
<div className="timeline">
<div className="events-wrapper">
<div className="events" id="foo">
<ol>
{newTimelineData.map((item, index) => (
<li key={item.id}>
<a
href="#0" onClick={()=> this.setHeaders(item)}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}
className={index === 0 ? 'selected' : null}>
<Moment unix format="DD MMM">
{item.scheduledFor / 1000}
</Moment>
</a>
</li>
))}
</ol>
<span className="filling-line" aria-hidden="true" />
</div>
{/* .events */}
</div>
{/* .events-wrapper */}
<ul className="cd-timeline-navigation">
<li>
<a href="#0" className="prev inactive">
Prev
</a>
</li>
<li>
<a href="#0" className="next">
Next
</a>
</li>
</ul>
{/* .cd-timeline-navigation */}
</div>
{/* .timeline */}
<div className="events-content">
<ol>
{newTimelineData.map((item, index) => (
<li
key={item.id}
className={index === 0 ? 'selected' : null}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Job</b> : {item.jobName}</div>
{isNotEmpty(joiningDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Joined Date : </b>{joiningDate}</div>}
</div>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',padding:0}}><b>Stage</b> : {this.props.stage}</div>
{isNotEmpty(offerDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 0,paddingRight:0}}><b>Offer Date : </b>{offerDate}</div>}
</div>
<br></br>
<div className="row">
<div className="col-sm-12" style={{fontSize:'1rem',paddingLeft: 0}}><b>Comments</b> :<br></br>{item.comments}</div>
</div>
</li>
))}
</ol>
</div>
{/* .events-content */}
</div>
{/* Horizontal Timeline end */}
{/*</div>*/}
{/*</div>*/}
</div>
</div>
<div className="modal-footer">
<button style={{backgroundColor: '#8080808f',borderColor:'#8080808f'}}
type="button"
className="btn btn-primary waves-effect waves-light"
data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
Can anyone help?
See below snapshot for the work around I have tried suggested by #Jayavel.

Implemented a small workaround and hope it's fulfills your need, With my understanding you load your modal body with state and user will change something and you store those in the same state.
While closing the modal(close button) you need to reset the initial state i.e reset to default values.
Is that right !!! check this demo
what you need is,
store your default state like below:
const initialState = {
isOpen: false,
value: "defaultvalue"
};
and in component :
class App extends Component {
constructor(props) {
super(props);
this.state = initialState; // stored defaultstate
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
}
toggleModalClose = () => { // modal close to reset input val
this.setState(initialState);
}
handleChange = (e) => {
this.setState({
value: e.target.value //input new value
});
}
render() {
return (
<div className="App">
<button onClick={this.toggleModal}>
Open the modal
</button>
<Modal show={this.state.isOpen}
onClose={this.toggleModalClose}>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</Modal>
</div>
);
}
}
Hope this helps.

Related

How to open only one Modal with using Modal template that I created

I was able to use the map method to display my static data in each container. There's a Modal template I created in order to provide more object/values info but if I click the button it opens all the modals of each containers at the same time because Modal tag wasn't assigned with unique index number when I mapped through my static data. Big brothers, please look at my codes and teach me how I can open only one associated Modal.
I created function Modal (template) and import to function Projects
function Modal({closeModal}) {
return (
<div className="modal-main">
<div className='modal-card'>
<img src="" />
<div className='modal-info'>
<div className='modal-title'>
<p className="title">title</p>
</div>
<div className='modal-body'>
<p className="tech">tech</p>
<p className="description">description</p>
<p className="github">github</p>
<p className="website">website</p>
</div >
<Button>detail</Button>
<Button onClick={()=> closeModal(false)}>close</Button>
</div>
</div>
</div>
)
}
export default Modal
function Projects() {
const [openModal, setOpenModal] = useState(false);
const [oneProject, setOneProject]
= useState(list_of_projects)
return (
<div className="section-header text-center mt-5">
<h4>projects</h4>
<p>list of proejcts</p>
<div className="proj-container">
{oneProject.map((item, index)=> {
return(
<div className='proj-map mx-2 my-2'key={index} >
<button type='button' className="btn btn-link " onClick={() => setOpenModal(true)}>
<div className=" proj-card card">
<img className='proj-img' src={item.thumbnail} style={{ width:300, height:300 }}/>
<div className="proj-text card-text">
<h3 className='title'>{item.title}</h3>
<h5 className='description'>description</h5>
<br/>
<h4>+</h4>
</div>
</div>
</button>
{openModal && <**Modal** closeModal={setOpenModal} /> }
</div>
)
})}
</div>
</div>

Sending request to elasticsearch using axios to map cards

I have a frontend react app that have cards, search bar, and filters. So to map the cards that I have, I want to send a request to elasticsearch (port:9200) using axios to save all the data in array and map my cards as I want, can you please help me?
Edit: I update the code here and include all of it, but there is no card mapped
function CreateCards(NCARMap) {
return(
<SimpleCard
key={NCARMap.id}
theCardId={NCARMap.id}
cardType={NCARMap.approvetool}
cardNum={NCARMap.num}
cardName={NCARMap.name}
cardDate={NCARMap.date}
// cardCategory={NCARMap.cardCategory}
// cardSource={NCARMap.cardSource}
cardDesc={NCARMap.summary}
cardURL={NCARMap.image}
/>
);
}
//create the class
export default class OfficialDocument extends Component {
constructor(props) {
super(props);
this.state = {
NCARMap: [],
NCARMapAS: [],
};
}
componentDidMount(){
//Get NCARMap data, NCARMapAS used for filtring and sorting the cards
axios.get('http://localhost:9200/ncar_index/ncar/_search')
.then(resp => {
console.log(resp)
this.setState({
NCARMap: resp._source,
NCARMapAS:resp.data
})
console.log(this.state.NCARMap)
})
}
handleChange(event) {
const search_query = event.target.value;
}
render(){
return(
//HTML FILE Converted to React
<div>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta httpEquiv="X-UA-Compatible" content="ie=edge" />
<title>منشآت</title>
<link rel="shortcut icon" href="/images/favicon.png" type="image/x-icon" />
{/*============= ScrollToTop Section Starts Here =============*/}
<div className="overlayer" id="overlayer">
<div className="loader">
<div className="loader-inner" />
</div>
</div>
<i className="fas fa-angle-up" />
<div className="overlay" />
{/*============= ScrollToTop Section Ends Here =============*/}
{/*============= Header Section Starts Here =============*/}
<header className="header-section">
<div className="container">
<div className="header-wrapper">
<div className="logo-area">
<div className="logo">
<a href="/">
<img src="/images/logo/logo.png" alt="logo" />
</a>
</div>
<div className="support headFont">
الصفحة الرئيسية
</div>
</div>
<ul className="menu headFont">
<li>
{/*Here we need to change the herf link*/}
الوثائق و المحفوظات
</li>
<li>
الأخبار
</li>
<li>
{/*Here we need to change the herf link*/}
التغريدات
</li>
{/*Here we need to change the herf link*/}
{/* I want to know the diffrence between the two below */}
<li className="d-md-none text-center">
تسجيل دخول
</li>
</ul>
<div className="header-bar d-lg-none">
<span style={{backgroundColor: '#00A7CF'}} />
<span style={{backgroundColor: '#00A7CF'}} />
<span style={{backgroundColor: '#00A7CF'}} />
</div>
{/* <div class="header-right"> */}
{/*Here we need to change the herf link*/}
{/* تسجيل دخول
</div> */}
</div>
</div>
</header>
{/*============= Header Section Ends Here =============*/}
{/*============= Banner Section Starts Here =============*/}
<section className="banner-2 bg_img" data-background="/images/banner/background3.png">
<div className="container">
<div className="banner-content-2">
<h1 className="title cl-white">مرحباً بك في قسم الوثائق والمحفوظات</h1>
<p className=" cl-white">يحتوي هذا القسم على الوثائق والمحفوظات المعتمدة من المركز الوطني للوثائق والمحفوظات</p>
<form className="search-form round">
<input type="text" style={{textAlign: 'right', color: 'black'}} placeholder="... ابحث هنا" />
<button type="submit"><i className="flaticon-search" /> <span className="d-none d-sm-inline-block">ابحث</span></button>
</form>
</div>
</div>
</section>
{/*============= Banner Section Ends Here =============*/}
{/*============= How Search Section Starts Here =============*/}
<div className="how-search-section padding-bottom mt--93">
<div className="container">
<div className="row mb-30-none justify-content-center">
<div className="filter-rtl">
{/*begin::Body*/}
<div className="card-body filters">
{/*begin::Form*/}
<form>
{/*begin::Categories*/}
<div className="form-group mb-11">
<label className="font-size-h3 font-weight-bolder text-dark mb-7">التنصيفات</label>
{/* start dropdown menue */}
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
أداة الاعتماد
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">أمر ملكي</a>
<a class="dropdown-item" href="#">مرسوم ملكي</a>
<a class="dropdown-item" href="#">قرار مجلس الوزراء</a>
<a class="dropdown-item" href="#">أمر سامي</a>
<a class="dropdown-item" href="#">قرار وزاري</a>
<a class="dropdown-item" href="#">قرار مجالس وهيئات</a>
<a class="dropdown-item" href="#">قرار إداري</a>
<a class="dropdown-item" href="#">توجيه سامي</a>
</div>
</div>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
فئة الوثيقة
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">الاتفاقيات و المعادات الدولية العامة</a>
<a class="dropdown-item" href="#">الاتفاقيات الدولية الثنائية</a>
<a class="dropdown-item" href="#">الاتفاقيات الدولية متعددة الأطراف</a>
</div>
</div>
</div>
{/* end dropdown menue */}
{/* Start: : DateRangePickerComponent */}
<DateRangePickerComponent></DateRangePickerComponent>
{/* End: : DateRangePickerComponent */}
{/*end::Categories*/}
<button type="submit" className="btn btn-primary font-weight-bolder mr-2 px-8">إعادة ضبط</button>
<button type="reset" className="btn-submit btn btn-clear font-weight-bolder text-muted px-8">بحث</button>
</form>
{/*end::Form*/}
</div>
{/*end::Body*/}
</div>
<div className="general-card">
{this.state.NCARMap.map(CreateCards)}
{console.log(this.state.NCARMap)}
</div>
</div>
</div>
</div>
{/*============= How Search Section Ends Here =============*/}
{/*============= Footer Section Starts Here =============*/}
<footer className="footer-section pt-70-145">
<div className="dot-slider bg_img" />
<div className="container">
<div className="row mb--50 justify-content-between">
<div className="col-sm-8 col-lg-4">
<div className="footer-widget widget-about">
</div>
</div>
</div>
</div>
<div className="footer-bottom cl-white">
<p>جميع الحقوق محفوظة © 2021</p>
</div>
</footer>
{/*============= Footer Section Ends Here =============*/}
</div>
)}
}
You need to add render method to your class component
export default class OfficialDocument extends React.Component {
constructor(props) {
super(props);
this.state = {
NCARMap: [],
NCARMapAS: [],
// need to add status
status: 'idle',
};
}
componentDidMount() {
//Get NCARMap data, NCARMapAS used for filtring and sorting the cards
this.setState({
status: 'pending',
});
axios
.get('http://localhost:9200/ncar_index/ncar/_search')
.then((resp) => {
console.log(resp);
this.setState({
NCARMap: resp._source,
NCARMapAS: resp.data,
status: 'success',
});
console.log(this.state.NCARMap);
})
.catch(() => {
this.setState({
status: 'error',
});
});
}
render() {
return (
<div>
{this.state.status === 'pending' && <div>Loading...</div>}
{this.state.status === 'error' && <div>Error</div>}
{this.state.status === 'success' && this.NCARMap.map((item) => {
return <CreateCards key={id} {...item} />;
})}
</div>
);
}
}
I answer this by receives them as objects:
code
<div className="general-card1">
{this.state.noPlaceFound ? (
<h3 className="noPlaceFound">
<i className="fas fa-exclamation-circle fa-sm WarnIcon"></i>
لا يوجد نتائج
</h3>
) : (
this.state.TweetsMap.map((v) => CreateCards(v._source))
)}
</div>

How to open specific post dropdown menu without effecting the others?

I have data that I am looping through and I have a slight issue with a dropdown menu. Whenever I click the dropdown button for a single post all the other posts open. And I don't know to solve it.
Here is the React code
const Post = () {
const [open, setOpen] = useState(false)
return(
{posts.map((post) => {
return (
<div className="card" key={post.postId}>
<div className="card-header">
<div className="card-header__avatar">
<img
src="https://source.unsplash.com/user/erondu/40x40"
alt=""
/>
</div>
<div className="card-header__username">
<span>
<strong>
{post.firstname} {post.lastname}
</strong>
</span>
<br />
<span>
<small>{date}</small>
</span>
</div>
<div
className="card-header__moreBtn"
onClick={() => setOpen(!open)}
>
<img src={More} alt="" />
{open && ( ------> here is where the problem comes
<div class="dropdown-wrapper">
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<Link href="#d" onClick={deletePost}>Edit</Link>
</li>
<li class="dropdown-menu__item">
<Link className="dropdown-menu__item__link" onClick={deletePost}>Delete</Link>
</li>
</ul>
</div>
)}
</div>
</div>
<div className="postDescription">
<p>{post.postDescription}</p>
</div>
<div className="imgPost">
<img src={post.image} alt="" />
</div>
</div>
)
})}
)
}
Here is a picture
Any help will suffice and I appreciate your time.
You're using the same state value for all items in your loop, so naturally they are going to all follow the same directive.
I would recommend creating a PostItem component that maintains its own state. Something like this:
const PostItem = ({post}) => {
const [open, setOpen] = useState(false)
return (
<div className="card" key={post.postId}>
<div className="card-header">
<div className="card-header__avatar">
<img
src="https://source.unsplash.com/user/erondu/40x40"
alt=""
/>
</div>
<div className="card-header__username">
<span>
<strong>
{post.firstname} {post.lastname}
</strong>
</span>
<br />
<span>
<small>{date}</small>
</span>
</div>
<div
className="card-header__moreBtn"
onClick={() => setOpen(!open)}
>
<img src={More} alt="" />
{open && (
<div class="dropdown-wrapper">
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<Link href="#d" onClick={deletePost}>Edit</Link>
</li>
<li class="dropdown-menu__item">
<Link className="dropdown-menu__item__link" onClick={deletePost}>Delete</Link>
</li>
</ul>
</div>
)}
</div>
</div>
<div className="postDescription">
<p>{post.postDescription}</p>
</div>
<div className="imgPost">
<img src={post.image} alt="" />
</div>
</div>
)
})
}
const AllPosts = ({posts}) {
return(
{posts.map(post => <PostItem post={post} />
)
}
Now each PostItem has a separate, internal instance of open in its own state and will act independently from the others.

How to open only one div inside map function in react show it cannot open other div element

this is my code part where i have used state and also setstate functin so I can toggle state but it is in map function so it is also opening other div i just wanted to know is it possible to open only one div using toggle function
this.state = {
show: false
}
commentInputHandler = () => {
console.log("working")
this.setState({
show: !this.state.show
})
}
<div className="col-lg-8 offset-lg-2 pb-5">
{this.state.posts.map(post => (
<div key={post._id} className="card mt-4">
<div className="card-body">
<div className="d-flex justify-content-between align-items-center">
<h4 className="card-title w-75">{post.title}</h4>
<div className="w-25 text-right">
<span onClick={() => this.deletePost(post._id)} className="badge badge-danger cp">Delete</span>
<span className="badge badge-primary cp ml-3">
<Link className="text-white" to={`/postupdate/${post._id}`}>Update</Link>
</span>
</div>
</div>
<p className="card-text">
{post.body}
</p>
</div>
<div className="card-footer">
<div className="d-flex justify-content-end">
<span onClick={this.commentInputHandler} className="badge badge-pill badge-primary mr-3 cp">Comment</span>
<span onClick={this.handleClickOpen} className="badge badge-pill badge-info cp">View comment</span>
</div>
{this.state.show ?
<div>
<form className="mt-3">
<input
type="text"
className="form-control"
placeholder="Add comment"
/>
<div className="d-flex justify-content-end">
<button className="btn btn-primary btn-sm mt-2">Comment</button>
</div>
</form>
</div> : null
}
</div>
</div>
))}
</div>
Right now show state holds for only one boolean, you might change it to an object that will hold each post show condition with _id as key (of course you can add it direct into posts state, just you didn't attach it to your code...)
this.state = {
//inital as empty object
show: {}
}
componentDidMount() {
// I update state through didMount, though it is not the only truth and depends on rest code either logic
let show = {}
this.state.posts.map(post => show[post._id] = false)
this.setState({show})
}
Now you can change commentInputHandler into something dynamic
<span onClick={()=>this.commentInputHandler(post._id)} className="badge badge-pill badge-primary mr-3 cp">Comment</span>
commentInputHandler = id => {
const { show } = this.state
this.setState({
show: {...show, [id]: !show.id}
})
}
and adapt your checker
{this.state.show[post._id] ? ...
Right now, you have a single state.show that is shared by all the elements generated by map. You could make state.show an array but there is a much better way to handle this.
You should create a separate component where you will put all the code inside your map function. Put state.show and commentInputHandler inside that new child component. Then each child component will be able to show/hide itself independently of the other ones
Parent
{this.state.posts.map(post => <PostComponent key={post.id} post={post}/>)}
PostComponent
this.state = { show: false }
commentInputHandler = () => {
...
render()
return (
<div className="card mt-4">
...

TypeError: Cannot read property 'title' of undefined on React

Consistently getting TypeError: Cannot read property 'title' of undefined when trying to load of my page. I am certain its related to my props but cannot figure what I am doing wrong.
I've tried going through every single prop and editing it but I continue to get the same error just for the next "person title" after.
import React from "react";
const Personcard = props => {
const handleUpdate = () => {
props.handleEdit(props.person.id);
};
return (
<div className="container">
<div className="containerUsers">
<div className="card">
<img
// src={props.person.primaryImage.imagineUrl}
id="primaryImageUsers"
alt=""
/>
<div className="card-body">
<div className="card-title">
<h2>
{props.person.title === "Mr" && (
<span id="titleUsers"> {props.person.title}</span>
)}
</h2>
</div>
</div>
<div className="card-text">
<h4>
<span id="headlineUsers" value={props.person.headline}>
{" "}
</span>
</h4>
<p>
<span id="summaryUsers" value={props.person.summary}>
{" "}
</span>
</p>
<p>
<span value={props.person.skills}> </span>
</p>
</div>
<button
type="button"
className="btn btn-warning"
onClick={handleUpdate}
>
{" "}
Update{" "}
</button>
<button type="button" className="btn btn-danger">
Delete
</button>
</div>
</div>
</div>
);
};
My goal is to display registered users on a homepage.
What you actually need to do is check for props.person whether it exists or not.
There are two cases:
It exists: we return the containerUsers.
It doesn't: we return a loading compoent.
We can check for it as this props.person ? true:false, true will be where we return the containerUsers, false where we will be returning the loading component.
import React from "react";
const Personcard = props => {
const handleUpdate = () => {
props.handleEdit(props.person.id);
};
return (andleUpdate = () => {
props.handleEdit(props.person.id);
};
return (
<div className="container">
{
props.person ? (
<div className="containerUsers">
<div className="card">
<img
// src={props.person.primaryImage.imagineUrl}
id="primaryImageUsers"
alt=""
/>
<div className="card-body">
<div className="card-title">
<h2>
{props.person.title === "Mr" && (
<span id="titleUsers"> {props.person.title}</span>
)}
</h2>
</div>
</div>
<div className="card-text">
<h4>
<span id="headlineUsers" value={props.person.headline}>
{" "}
</span>
</h4>
<p>
<span id="summaryUsers" value={props.person.summary}>
{" "}
</span>
</p>
<p>
<span value={props.person.skills}> </span>
</p>
</div>
<button
type="button"
className="btn btn-warning"
onClick={handleUpdate}
>
{" "}
Update{" "}
</button>
<button type="button" className="btn btn-danger">
Delete
</button>
</div>
</div>
</div>
) : null
}
);
};
In the code I provided, instead of null, return a loading component if you want.
it's the last line in the return function. should be: ( <Loading /> ) for example.
So, I did this because, person is not defined at the first mount of the component, that's why we checked for it.
Currently this will solve the problem, but I prefer if you pass a default value for props.person from the parent component, it can be a plain object {} with nothing without it.

Resources