pass value of clicked list to EditForm to edit - javascript

I am doing reactjs and redux for developing dashboard. I have done add, delete but editing is not working. When user clicks on item, the textfield should display with its current value and able to submit the changes. I can show textfield when clicked but could not show the current value of that item which is clicked. To display textField i have to use onClick on the li tag otherwise i could pass data like using this.props.editTab(tab). How can i now send data of clicked item to editTab action ?
constructor(props) {
super(props);
this.state = { open: false, editing: false };
}
editTab() {
const tabs = _.map(this.props.tabs, (tab) => {
if (tab.editable) {
return (
<li
className="list-group-items delete-tab-list"
onClick={() => this.setState({ editing: true })}
key={tab.id}
>
<i className="material-icons">{tab.icon}</i>{tab.name}
</li>
);
}
});
return (
<div className="device-action">
<Dialog
title="Update a Tab"
modal={false}
bodyStyle={{ background: '#fff' }}
contentStyle={customContentStyle}
actionsContainerStyle={{ background: '#fff' }}
titleStyle={{ background: '#fff', color: '#1ab394' }}
open={this.props.createTab.open}
onRequestClose={this.props.closeTabIcon}
>
<ul className="list-group">
{ this.state.editing ?
<EditForm
tab={this.props.tabs}
editing={this.state.editing}
/> :
tabs
}
</ul>
</Dialog>
</div>
);
}
handleEditSave = (name, icon) => {
this.props.editTab(name, icon);
}
render() {
return (
<div>
<form onSubmit={this.handleEditSave}>
<div className="tab-name">
<TextField
floatingLabelText="Name"
onChange={(name) => { this.setState({ name: name.target.value }); }}
/>
</div>
<div className="icon">
<AutoComplete
floatingLabelText="select any icon"
filter={AutoComplete.noFilter}
openOnFocus
onNewRequest={(e) => { this.setState({ icon: e.id }); }}
/>
</div>
<button className="btn">Save</button>
</form>
</div>
);
}
How can i pass clicked item data to EditForm component so i can trigger my action in this.props.editTab(tab) this way ?

You can simply track the tab you editing by saving it on the state.
This will work only if you want to edit 1 tab at time. otherwise you can use Object/Array.
constructor(props) {
super(props);
this.state = { open: false, editing: null };
}
editTab() {
const tabs = _.map(this.props.tabs, (tab) => {
if (tab.editable) {
return (
<li
className="list-group-items delete-tab-list"
onClick={() => this.setState({ editing: tab })}
key={tab.id}
>
<i className="material-icons">{tab.icon}</i>{tab.name}
</li>
);
}
});
const { editing } = this.state;
// editing is the Tab object that we edit
if (editing)
console.log("Editing tab: " + editable.name);
return (
<div className="device-action">
<Dialog
title="Update a Tab"
modal={false}
bodyStyle={{ background: '#fff' }}
contentStyle={customContentStyle}
actionsContainerStyle={{ background: '#fff' }}
titleStyle={{ background: '#fff', color: '#1ab394' }}
open={this.props.createTab.open}
onRequestClose={this.props.closeTabIcon}
>
<ul className="list-group">
{ this.state.editing ?
<EditForm
tab={this.props.tabs}
editing={this.state.editing}
/> :
tabs
}
</ul>
</Dialog>
</div>
);
}
handleEditSave = (name, icon) => {
this.props.editTab(name, icon);
}
render() {
return (
<div>
<form onSubmit={this.handleEditSave}>
<div className="tab-name">
<TextField
floatingLabelText="Name"
onChange={(name) => { this.setState({ name: name.target.value }); }}
/>
</div>
<div className="icon">
<AutoComplete
floatingLabelText="select any icon"
filter={AutoComplete.noFilter}
openOnFocus
onNewRequest={(e) => { this.setState({ icon: e.id }); }}
/>
</div>
<button className="btn">Save</button>
</form>
</div>
);
}

Related

show/hide button in React Js

There is an edit button. that edit button, I want to show the button if those items were created in less than 6 hours. The button should not be shown for more than 6 hours. I use moment js to calculate time. time calculation is working perfectly. but button visibility, not working.
Current time state
timenow:moment().format('H')
This is my condition
{(moment(post.createdAt).add(6,'hour').format('H')< this.state.timenow)||(
<Button
variant="outline-info"
className="cardbutton"
size="sm"
onClick={this.editPost.bind(this, post._id, post.message)}
>
Edit
</Button>)}
Complete component
import React, { Component } from "react";
import { Card, Button, Badge, Modal } from "react-bootstrap";
import pic2 from "./pic2.jpg";
import "./Forum.css";
import { BiMessageRounded } from "react-icons/bi";
import axios from "axios";
import moment from "moment";
import { RiDeleteBin6Line } from "react-icons/ri";
import { Link } from "react-router-dom";
//import '../NotificationBar/SideNotification.css';
class Forum extends Component {
constructor(props) {
super(props);
this.state = {
message: "",
posts: [],
showModel: false,
showConfirm: false,
showDeleteConfirm: false,
deletePost: "",
editPost: { message: "", id: "" },
visiblequestions: 10,
visibletype: "",
faculty:"",
timenow:moment().format('H')
};
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.loadmore = this.loadmore.bind(this);
this.handletypechange = this.handletypechange.bind(this);
this.handlefaculty = this.handlefaculty.bind(this);
}
handleChange(event) {
this.setState({ message: event.target.value });
}
handleClick(event) {
console.log(this.state.message);
event.preventDefault();
const message = { message: this.state.message ,faculty:this.state.faculty,privacytype:this.state.visibletype};
axios.post("http://localhost:4000/Forum", message).then((res) => {
console.log(res);
console.log(res.data);
this.handleCloseModal();
this.getAllPosts();
});
this.setState({
message: "",
});
}
componentDidMount() {
this.getAllPosts();
this.timelimit();
}
getAllPosts = () => {
axios
.get("http://localhost:4000/Forum/home")
.then((res) => this.setState({ posts: res.data.reverse() }));
};
deletePost = (id) => {
axios
.delete("http://localhost:4000/Forum/" + this.state.deletePost)
.then((res) => {
console.log(res);
this.handleDeleteCloseModal();
this.getAllPosts();
});
};
editPost = (id, message) => {
this.setState((currentState) => ({
...currentState,
showModel: true,
editPost: { message: message, id: id },
}));
console.log(this.state);
};
updatePost = () => {
axios
.patch("http://localhost:4000/Forum/" + this.state.editPost.id, {
message: this.state.editPost.message,
})
.then((res) => {
this.setState((currentState) => ({
...currentState,
showModel: false,
}));
this.getAllPosts();
});
};
onChangehandler = (e) => {
e.persist();
this.setState((currentState) => ({
...currentState,
editPost: { ...currentState.editPost, message: e.target.value },
}));
};
cancleEdit = () => {
this.setState((currentState) => ({ ...currentState, showModel: false }));
this.getAllPosts();
};
handleModal = () => {
this.setState({ showConfirm: true });
};
handleCloseModal = () => {
this.setState({ showConfirm: false });
};
handleDeleteModal = (id) => {
this.setState(() => ({ showDeleteConfirm: true, deletePost: id }));
};
handleDeleteCloseModal = () => {
this.setState({ showDeleteConfirm: false });
};
loadmore() {
this.setState((old) => {
return { visiblequestions: old.visiblequestions + 5 };
});
}
handletypechange(event) {
this.setState(
{ visibletype: event.target.value },
console.log(this.state.visibletype)
);
}
handlefaculty(event) {
this.setState(
{ faculty: event.target.value },
console.log(this.state.faculty)
);
}
timelimit(id){
if(this.state.timenow<2.30){
console.log("yes");
}else{
console.log("no");
}
console.log(this.state.timenow);
}
render() {
return (
<div>
<div class="sidenav">
<h5 style={{ textAlign: "center", color: "white" }}>
Notification Bar
</h5>
</div>
<div className="divstyle">
<Card className="forumstyle">
<Card.Header as="h5">Post Question Here</Card.Header>
<Card.Body>
<Card.Title></Card.Title>
<Card.Text>
<textarea
style={{ width: "460px" }}
placeholder="Please write question here..."
value={this.state.message}
onChange={this.handleChange}
/>
</Card.Text>
</Card.Body>
<div>
<select
className="form-select-sm select"
aria-label="Default select example"
onChange={this.handletypechange}
>
<option defaultValue hidden>Select Type</option>
<option value="all">All</option>
<option value="academic">Academic</option>
<option value="student">Student</option>
</select>
{this.state.visibletype === "student" && (
<select
className="form-select-sm select"
aria-label="Default select example"
onChange={this.handlefaculty}
>
<option defaultValue hidden>Select Faculty</option>
<option value="All">All</option>
<option value="Engineering">Engineering</option>
<option value="Information Technology">
Information Technology
</option>
<option value="Architecture">Architecture</option>
<option value="Business">Business</option>
</select>
)}
</div>
</Card>
<Button
className="button"
variant="primary"
onClick={this.handleModal}
>
Post
</Button>
</div>
<div style={{ backgroundColor: "rgba(192,192,192,0.3)" }}>
{this.state.posts
.slice(0, this.state.visiblequestions)
.map((post) => (
<Card
key={post._id}
style={{
width: "500px",
marginLeft: "30%",
marginBottom: "30px",
marginTop: "20px",
border: "1px solid grey",
}}
>
<Card.Header>
<img
src={pic2}
style={{ width: "20px" }}
className="rounded mr-2"
alt=""
/>
Anushka Praveen
<small style={{ float: "right" }}>
{moment(post.createdAt).fromNow()}
</small>
</Card.Header>
<Card.Body>
<Card.Text>{post.message}</Card.Text>
<Link
to={{
pathname: "Forum/ForumReply",
query: { id: post._id },
}}
>
<Button
variant="outline-info"
className="cardbutton"
size="sm"
>
<BiMessageRounded style={{ marginRight: "2px" }} />
Reply
<Badge className="badgestyle" variant="info">
{post.reply.length}
</Badge>
</Button>
</Link>
{moment(post.createdAt).add(6,'hour').format('H')>this.state.timenow &&(
<Button
variant="outline-info"
className="cardbutton"
size="sm"
onClick={this.editPost.bind(this, post._id, post.message)}
>
Edit
</Button>)}
<Button
variant="outline-danger"
className="carddeletebutton"
size="sm"
onClick={() =>
this.handleDeleteModal(post._id)
} /* {this.deletePost.bind(this, post._id)} */
>
<RiDeleteBin6Line />
</Button>
</Card.Body>
</Card>
))}
<div class="col-md-12 p-3 text-center">
{this.state.visiblequestions < this.state.posts.length && (
<button
type="button"
class="btn btn-outline-info"
onClick={this.loadmore}
>
Read more
</button>
)}
</div>
</div>
<Modal show={this.state.showModel}>
<Modal.Header>
<Modal.Title>Edit Question</Modal.Title>
</Modal.Header>
<Modal.Body>
<textarea
style={{ width: "29rem" }}
value={this.state.editPost.message}
onChange={this.onChangehandler}
>
{this.state.editPost.message}
</textarea>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.cancleEdit}>
Close
</Button>
<Button variant="primary" onClick={this.updatePost}>
Save
</Button>
</Modal.Footer>
</Modal>
<Modal show={this.state.showConfirm}>
<Modal.Header>
<Modal.Title>Post Question</Modal.Title>
</Modal.Header>
<Modal.Body>Do you want post this Question?</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.handleCloseModal}>
Close
</Button>
<Button variant="danger" onClick={this.handleClick}>
Post Question
</Button>
</Modal.Footer>
</Modal>
<Modal show={this.state.showDeleteConfirm}>
<Modal.Header>
<Modal.Title>Delete Question</Modal.Title>
</Modal.Header>
<Modal.Body>Do you want Delete this Question?</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.handleDeleteCloseModal}>
Close
</Button>
<Button variant="danger" onClick={this.deletePost}>
Delete Question
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default Forum;
Maybe trying to conditionally render it this way will help.
{(!(moment(post.createdAt).add(6,'hour').format('H')< this.state.timenow))?
<Button
variant="outline-info"
className="cardbutton"
size="sm"
onClick={this.editPost.bind(this, post._id, post.message)}
>
Edit
</Button>:<>"empty"</>}
Your conditional rendering seems fine. || operator evaluates the left-hand side and if it is false, it moves to the right hand side. Whereas && operator evaluates the left-hand side and continues if it is true
You want to show the button, if it is less than 6 hours. So you want (moment(post.createdAt).add(6,'hour').format('H') < this.state.timenow) evaluate to true and render the Button only if the statement is true
{(moment(post.createdAt).add(6,'hour').format('H') < this.state.timenow) && (
<Button
variant="outline-info"
className="cardbutton"
size="sm"
onClick={this.editPost.bind(this, post._id, post.message)}
>
Edit
</Button>)}

Changing variable in one file conflicts the data for other file in React JS

I'm having weird problem in React JS. I have two classes named as Notes.js and DataTables.js
I'm using DataTables in Note.js like this
<DataTables
keyField="id"
columns={columns}
url={this.state.url}
useCallBack={true}
onEdit={this.onEdit}
/>
Please Note that DataTables.js is my own custom created DataTable.js not react-datatable.
All the work like fetching data from URL and showing it in tabular form is in DataTables.js file.
Note.js Code:
import React, { Component } from "react";
import { Constant } from "../shared/Constants";
import DataTables from "../shared/DataTables";
import { Modal, Button } from "react-bootstrap";
import BreadCrumb from "../shared/BreadCrumb";
import "../Style.css";
const columns = Constant.notes;
export class Notes extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
url: "notes/get_notes",
showModal: false,
note: [],
};
this.onEdit = this.onEdit.bind(this);
this.onAdd = this.onAdd.bind(this);
this.onUpdate = this.onUpdate.bind(this);
this.saveNote = this.saveNote.bind(this);
}
onUpdate(key, value) {
let noteData = this.state.note;
noteData[key] = value;
this.setState({
note: noteData,
});
}
saveNote(e) {
e.preventDefault();
}
onEdit(n) {
this.setState({
note: n,
showModal: true,
});
}
onAdd() {
this.setState({
note: [],
showModal: true,
});
}
render() {
return (
<>
<Modal
show={this.state.showModal}
aria-labelledby="example-modal-sizes-title-lg"
onHide={() => this.setState({ showModal: false })}
>
<form method="post" onSubmit={this.saveNote}>
<Modal.Header>
<Modal.Title>My Note</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<label className="text-muted">Note Title</label>
<input
type="text"
placeholder="Note Title"
className="form-control"
ref="title"
value={this.state.note.title}
onChange={(e) => this.onUpdate("title", e.target.value)}
/>
</div>
<div className="form-group">
<label className="text-muted">Content</label>
<textarea
onChange={(e) => this.onUpdate("content", e.target.value)}
className="form-control"
style={{ height: "250px" }}
placeholder="Content"
>
{this.state.note.content}
</textarea>
</div>
</div>
</div>
</Modal.Body>
<Modal.Footer>
<Button
variant="secondary"
onClick={() => this.setState({ showModal: false })}
>
Close
</Button>
<Button type="submit" variant="primary">
Save Note
</Button>
</Modal.Footer>
</form>
</Modal>
<BreadCrumb
title="My Notes"
useCallBack={true}
onAdd={this.onAdd}
active_link="Notes"
link=""
link_text="Add New"
/>
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<div className="card-title">Notes</div>
<DataTables
keyField="id"
columns={columns}
url={this.state.url}
useCallBack={true}
onEdit={this.onEdit}
/>
</div>
</div>
</div>
</div>
</>
);
}
}
export default Notes;
I'm having Problem in Note.js on onUpdate function
onUpdate(key, value) {
let noteData = this.state.note;
noteData[key] = value;
this.setState({
note: noteData,
});
}
Problem: When I update a field in Modal as you can see in my code, then my Table in DataTable.js automatically gets updated, I'don't why :/
Here is DataTables.js function where I'm sending data to onEdit function
const TableData = () => {
return (
<tbody>
{tableData.length === 0 ?
<tr>
<td className="text-center" colSpan="5"><strong>No Data Found</strong></td>
</tr>
:
tableData.map((tData) => (
<tr key={tData[this.props.keyField]}>
{this.props.columns.map((item, index) => (
<td key={index} className="table-content">
{index === 0 ?
[(useCallback === true ? <span key={"sub_"+index} className="link" onClick={() => this.props.onEdit(tData)}>{tData[item.dataField]}</span> :
<Link
to={
this.props.edit_link +
"/" +
tData[this.props.edit_key_first] + (this.props.edit_key_second ? "/" +
tData[this.props.edit_key_second] : '')
}
>
{tData[item.dataField]}
</Link>
)]
: (
tData[item.dataField]
)}
</td>
))}
</tr>
))}
</tbody>
);
};
Please check gif image below so you can understand it :P
You have an onChange function that is updating the content
onChange={(e) => this.onUpdate("content", e.target.value)}
If you don't want to change the content while typing then you will have to remove this.

Reactjs: How to perform edit action and open modal according to its respective id

I want to handle Edit/update action on my modal value of my blog.
All the actions ADD, EDIT, DELETE are working now
Only issue is on click every edit I am getting same blog data of 0th array
any suggestion on this. How can i handle this and open modal with respective to its id only ?
Thanks
//Blog.js
<Grid style={{padding: 0}} id="todo">
{activeBlogs.map((item, index) => (
<Cell key={item._id} data-id={item._id}>
<Card shadow={5} className="cards-grid">
{item.blog_image_link ?
(<CardTitle style={{color: '#fff', height: '200px',
width: 'auto', backgroundImage: `url(${item.blog_image_link})`, backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat'}}></CardTitle>) :
(<CardTitle className="card-title-image"></CardTitle>
)
}
<CardText>
<b>{item.blog_short_desc}</b>
</CardText>
<CardActions border>
<p>
<Button className="blog-read-me-button col-4" onClick={this.handleOpenDialog.bind(this, item._id)}>Read </Button>
{ isAuthenticated && (item.blog_by === user._id) ?
<span className="col=8">
<Button className="remove-btn-blog-post"
color="danger"
size="sm"
onClick= {this.onDeleteBlogClick.bind(this, item._id)} title="Delete Blog">
×
</Button>
<EditBlog onClick={() => this.replaceModalItem(this, item._id)} />
</span> : null }
</p>
<p style={{ fontStyle:'italic', fontWeight:'bold'}}>By-{item.blog_by_author} <span style={{float:'right',}}>{Moment(item.date).format('Do MMMM YYYY')}</span></p>
</CardActions>
</Card>
</Cell>
))}
</Grid>
//Edit.js (child component)
class EditBlog extends Component {
constructor(props) {
super(props);
this.state = {
modal: false,
requiredItem : null,
_id: '',
blog_short_desc: '',
blog_name: '',
blog_desc: '',
blog_image_link: '',
blog_by: '',
blog_by_author: ''
};
this.replaceModalItem = this.replaceModalItem.bind(this);
this.onTodoChange = this.onTodoChange.bind(this);
}
static propTypes = {
auth: PropTypes.object.isRequired,
updateBlog: PropTypes.func.isRequired,
editBlog: PropTypes.func.isRequired,
resume: PropTypes.object.isRequired,
}
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.name
})
}
toggle = (id) => {
this.setState({
modal: !this.state.modal
});
}
componentWillMount() {
this.props.resume["blogs"].map((blog) => {
this.setState({
updatable : false,
_id: blog._id,
blog_short_desc: blog.blog_short_desc,
blog_name: blog.blog_name,
blog_desc: blog.blog_desc,
blog_image_link: blog.blog_image_link,
blog_by: blog.blog_by,
blog_by_author: blog.blog_by_author
});
})
debugger
}
// replaceModalItem(id) {
// debugger
// this.setState({
// requiredItem : id
// })
// }
replaceModalItem(id) {
this.setState({
openDialog: true,
OpenEditDialog: true,
requiredItem: id
});
}
// titleHandler(e) {
// this.setState({ [e.target.name] : e.target.value });
// }
onTodoChange = (e) => {
this.setState({
[e.target.name] : e.target.value
});
}
onSubmit = (e, id) => {
e.preventDefault();
const updatedBlog = {
blog_short_desc: this.state.blog_short_desc,
blog_name: this.state.blog_name,
blog_desc: this.state.blog_desc,
blog_image_link: this.state.blog_image_link,
blog_by: this.props.auth["user"]._id,
blog_by_author: this.props.auth["user"].name
}
//update blog via updateblog action
this.props.updateBlog(id, updatedBlog, this.props.history);
alert("Blog updated successfully!");
debugger
//close modal
e.target.reset();
this.toggle();
}
render(){
return(
<span>
<a className="btn edit-btn-blog-post" href="#" onClick={this.toggle} title="Edit Blog">
<i className="fa fa-pencil" aria-hidden="true"></i>
</a>
<Modal
isOpen = {this.state.modal}
toggle = {this.toggle}
></Modal>
<Modal
isOpen = {this.state.modal}
toggle = {this.toggle}
>
<ModalHeader toggle={this.toggle} style={{fontWeight: "bold"}}>
Edit your blog {this.state.blog_name}
</ModalHeader>
<ModalBody>
<Form onSubmit={e => this.onSubmit(e, this.state._id, )}>
<FormGroup>
<Label for="blogHeading">Blog Heading</Label>
<Input type="text" name="blog_short_desc" id="blogHeading" placeholder="Update one liner"
onChange={this.onTodoChange} value={this.state.blog_short_desc}/>
<Label for="blogName">Blog Name</Label>
<Input type="text" name="blog_name" id="blogName" placeholder="Update blog name"
onChange={this.onTodoChange} value={this.state.blog_name}/>
<Label for="desc1">Description </Label>
<Input type="textarea" name="blog_desc" id="desc1" placeholder="Update your blog"
onChange={this.onTodoChange} value={this.state.blog_desc}/>
<Label for="imageUrl">Image Url</Label>
<Input type="text" name="blog_image_link" id="imageUrl" placeholder="Update image url (Optional)"
onChange={this.onTodoChange} value={this.state.blog_image_link}/>
<Button
color="dark"
style={{marginTop: '2rem'}}
block
>Edit blog</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
</span>
)
}
}
const mapStateToProps = state => ({
resume: state.resume,
auth: state.auth
})
export default connect(mapStateToProps, { updateBlog })(EditBlog);
//blog UI
Get your record data in componentDidMount and then use setState to populate your form.

First modal on each page not displaying data

I am making a workstation assessment website.
I am stuck with an issue I am having.
The modal is my a grandchild component (modal complete questions). I then have a component named questions as a parent and as the parent to that I have Admin Workstations.
Hierachy
1.AdminWorkstations,
2.Questions,
3.Modal,
(this is not full functionality of these components but is just for the use case I am asking for).
1.Parent gets WSAId(just a id).Passes down to questions.
2.Questions passes the modal component this.
3.Modal gets questions using this id.
However the first modal does not display.I have paginated the results of these page if this makes any diffrence.
this is my modal
import "./ViewWorkstationModal.css";
import React, { useState, useEffect } from "react";
import { Modal, DropdownButton, Dropdown } from "react-bootstrap";
function ModalCompletedQuestions(props) {
const [show, setShowState] = useState(0);
const [loadingToken, setLoadingToken] = useState(0);
const [answeredQuestions, setAnsweredQuestions] = useState([{}]);
useEffect(() => {
setLoadingToken(true);
let data = {
WSAId: props.WSAId
};
fetch("/get-completed-questions", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(recordset => recordset.json())
.then(results => {
setAnsweredQuestions(results.recordset);
});
}, []);
function handleClose() {
setShowState(false);
}
function handleShow() {
setShowState(true);
}
return (
<>
<>
<div className="header-container">
<button
className="btn btn-primary"
style={{ float: "right" }}
onClick={handleShow}
>
Response Overview
</button>
</div>
<div>
<Modal
size="lg"
style={{ width: "100%" }}
show={show}
onHide={handleClose}
animation={true}
>
<h3 style={{ textAlign: "center" }}>{props.workStation}</h3>
{answeredQuestions &&
answeredQuestions.map(function(question, index) {
if (
question.QuestionResponse === "Y" ||
question.QuestionResponse === "N"
) {
return (
<>
<div
style={{
backgroundColor: "#E6E6E6",
padding: "1px"
}}
>
<ul>
{" "}
<b> Q :</b>
<div style={{ float: "right" }}>✔️</div>
{question.QuestionWhenAnswered}
</ul>
</div>
</>
);
} else if (question.QuestionResponse === "P") {
return (
<>
<div
style={{
backgroundColor: "#BDBDBD",
padding: "1px"
}}
>
<ul>
<b> Q :</b>
{question.QuestionWhenAnswered}{" "}
<div style={{ float: "right" }}>❌</div>
{/* <br />
<b> S :</b>
{question.SuggestedSoloution} */}
</ul>
</div>
</>
);
}
})}
</Modal>
</div>
</>
</>
);
}
this is my questions component
class Questions extends React.Component {
constructor(props) {
super(props);
console.log(props);
this.state = {
...props,
questionsAccepted: [],
questionsAcceptedCounter: "",
selectedSet: [],
ViewActivityToken: false,
noteToBeAdded: "",
notesFromDB: [],
addNoteToken: false,
answeredQuestions: []
};
}
render() {
if (!this.state.ViewActivity) {
if (!this.state.viewDetails && !this.state.ViewActivityToken) {
console.log(moment.locale());
return (
<div>
<ModalCompletedQuestions
RUId={this.props.RUId}
workStation={this.props.workStation}
WSAId={this.props.WSAId}
/>
<Link
to={{
pathname: "/admin-view-full-user-wsa-responses",
state: {
WSAId: this.props.WSAId
}
}}
>
<button style={{ float: "right" }} className="btn btn-primary">
View Full Details
</button>
</Link>
<br />
<li>
<b>User Id: </b>
{this.props.RUId}
</li>
<li>
<b>Workstation: </b>
{this.props.workStation}
</li>
<li>
<b>Date: </b>
{moment(this.props.date).format("L")}
</li>
<li>
<b>Complete Token: </b>
{this.props.completeToken}
</li>
</div>
);
} else if (this.state.viewDetails && !this.state.ViewActivityToken) {
return (
<div>
<button
style={{ float: "right" }}
onClick={e =>
this.setState({
ViewActivity: false,
viewDetails: false,
ViewActivityToken: false,
addNoteToken: false
})
}
className="btn btn-secondary"
>
Revert
</button>
<br />
<br />
{this.state.selectedSet &&
this.state.selectedSet.map((item, index) => {
return (
<div>
<li>
{" "}
<b>{item.QuestionWhenAnswered}</b>{" "}
</li>
<li>{item.QuestionResponse}</li>
<li>{item.Accepted}</li>
</div>
);
})}
</div>
);
}
} else if (this.state.ViewActivity && !this.state.addNoteToken) {
return (
<>
<button
style={{ float: "right" }}
onClick={e =>
this.setState({
ViewActivity: false,
viewDetails: false,
ViewActivityToken: false,
addNoteToken: false
})
}
className="btn btn-secondary"
>
Revert
</button>
<br />
<li>
<b>User Id: </b>
{this.props.RUId}
</li>
<li>
<b>Workstation: </b>
{this.props.workStation}
</li>
<li>
<b>Date: </b>
{moment(this.props.date).format("DD/MM/YYYY")}
</li>
<li>
<b>Complete Token: </b>
{this.props.completeToken}
</li>
{this.state.notesFromDB &&
this.state.notesFromDB.map((item, index) => {
return (
<div
style={{
backgroundColor: "white",
border: "inset",
borderWidth: "0.2px"
}}
>
<div style={{ float: "right" }}>
{moment(item.CreationTime).format("HH:MM DD/MM/YYYY ")}
</div>
<div>
<b>{`${item.UserStatus} `}</b>
</div>
<div style={{ textAlign: "left" }}>{item.Notes}</div>
</div>
);
})}
<br />
<button
onClick={this.AddNoteBtn}
className="btn btn-primary"
style={{ width: "100%" }}
>
Add Note
</button>
</>
);
}
}
}
How come when the first is clicked the modal appears blank but the rest of the modals are filled with the right data.
Essentially it seems as if though the first modal is not performing the data fetch which is within the modal component.
Any extra information needed let me know but these seem to be the most important for this use case.
Any help is much appreciated.
I completed this by using a condition within the use effect.
useEffect(() => {
setLoadingToken(true);
let data = {
WSAId: props.WSAId
};
fetch("/get-completed-questions", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(recordset => recordset.json())
.then(results => {
setAnsweredQuestions(results.recordset);
});
}, [PUT YOUR CONDTION HERE]);
I simply just passed my props through so it says every time there is a new props do this.

Rendering component on long mouse click

I am trying to render a modal component on a long mouse click. If I just try to fire an alert it works but rendering doesn't seem to do the trick. I am assuming maybe If I have to return? Not quite sure. I created a function handleButtonPressDown to perform this task and the handleButtonRelease to clear interval in the event the user decides not to perform this action.
export class Dropdown extends React.Component<IProps> {
buttonPressTimer: any;
constructor(props: IProps) {
super(props);
this.handleButtonPress = this.handleButtonPress.bind(this);
this.handleButtonRelease = this.handleButtonRelease.bind(this);
}
public render() {
return (
<div style={{ alignSelf: "center" }}>
<ul className="nav nav-pills">
{filteredProbes.length === 0 ? (
<li className="nav-item dropdown ">
<div
className="dropdown-menu show"
x-placement="bottom-start"
style={{
display: "none"
}}
></div>
</li>
) : (
<li className="nav-item dropdown ">
<div
className="dropdown-menu show"
x-placement="bottom-start"
style={{
position: "relative",
willChange: "transform",
top: "5px",
overflowY: "scroll",
maxHeight: "200px",
color: "white"
}}
>
{this.props.searchState.isActive === false
? probes.map(probe => (
<a
onClick={() => this.props.onUpdateSelectedProbe(probe)}
className="dropdown-item"
onMouseDown={this.handleButtonPress}
onMouseUp={this.handleButtonRelease}
>
<div
className="dropdown-divider"
style={{ backgroundColor: "black" }}
></div>
{probe.companyPN}: {probe.description}
</a>
))
: filteredProbes.map(filterprobe => (
<a
onClick={() =>
this.props.onUpdateSelectedProbe(filterprobe)
}
className="dropdown-item"
>
<div className="dropdown-divider"></div>
{filterprobe.companyPN}: {filterprobe.description}
</a>
))}
</div>
</li>
)}
</ul>
</div>
);
}
handleButtonPress() {
this.buttonPressTimer = setTimeout(() => {
{/* Show the modal if showModal is true */}
this.props.modalState.showModal && (
<WedgeGroup
wedgeState={this.props.wedgeState}
onUpdateSelectedWedge={this.props.onUpdateSelectedWedge}
onUpdateShowModal={this.props.onUpdateShowModal}
onUpdateHideModal={this.props.onUpdateHideModal}
modalState={this.props.modalState}
/>
);
}, 1000);
}
handleButtonRelease() {
clearTimeout(this.buttonPressTimer);
}
}
You need to move the code that you have inside setTimeout to render function and use state to render WedgeGroup:
export class Dropdown extends React.Component<IProps> {
...
constructor(props: IProps) {
super(props);
this.state = {
showModal: false
};
...
}
public render() {
const showModal = this.props.modalState.showModal &&
this.state.showModal;
return (
<div style={{ alignSelf: "center" }}>
{
showModal && (
<WedgeGroup
wedgeState={this.props.wedgeState}
onUpdateSelectedWedge={this.props.onUpdateSelectedWedge}
onUpdateShowModal={this.props.onUpdateShowModal}
onUpdateHideModal={this.props.onUpdateHideModal}
modalState={this.props.modalState}
/>
);
}
//..... render other components
</div>
);
}
handleButtonPress() {
this.buttonPressTimer = setTimeout(() => {
this.setState({
showModal: true
})
}, 1000);
}
handleButtonRelease() {
clearTimeout(this.buttonPressTimer);
}
}
It will not render firstly because your are not triggering any mechanism that makes React render.
I'd suggest to you to remove this component from the setTimeout, place it inside the render (where it should be).
And finally manipulate your component state to show or hide your modal.
If you trigger a timer to show the modal view it will only appear after the change of the state, so in your case it will take 1s to show to the user, what may look not responsive.
// inside your handleButtonPress()
this.setState({
showModal: true
}}

Categories

Resources