Trying to open modal on button click - javascript

I am trying to open ANTD modal when i click on button on the form using the below code
This is HTML code:
<div>
<Button type="primary" size={buttonsize.size} onClick={createproject1}>
Add New Project
</Button>
<div>
<div>
<Modal
title="Add New project"
visible={setvisible.visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Input size="small" placeholder="Project Name" onChange={handleChange('projectName')} />
<br />
<br />
<Input size="small" placeholder="Project Number" onChange={handleChange('projectNumber')} />
<br />
<br />
<Input size="small" placeholder="Area" onChange={handleChange('area')} />
<br />
<br />
</Modal>
</div>
This is the hook and other state stuff:
const [visible, setvisible] = useState({ visible: false });
const createproject1 = (e) => {
setvisible.visible = true;
};
I am not sure where i am going in wrong direction.. could any one please let me know is there any way to open a modal that would be very grateful to me

From the docs:
Returns a stateful value, and a function to update it.
setvisible is a function, which allows you to update the state. You would need to call it like so:
setvisible({visible: true});
Since this is as simple as a bool, and object isn't necessary here:
const [visible, setVisible] = useState(false)
Then you could simply call:
setVisible(true);
Since you're still having issues, let me make this dirt simple for you:
const [visible, setVisible] = useState(false)
And your component:
<div>
<Button type="primary" size={buttonsize.size} onClick={() => setVisible(true)}>
Add New Project
</Button>
<div>
<div>
<Modal
title="Add New project"
visible={visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Input size="small" placeholder="Project Name" onChange={handleChange('projectName')} />
<br />
<br />
<Input size="small" placeholder="Project Number" onChange={handleChange('projectNumber')} />
<br />
<br />
<Input size="small" placeholder="Area" onChange={handleChange('area')} />
<br />
<br />
</Modal>
</div>

For creating hooks as single value variable, you don't have to create hooks like this..
const [visible, setvisible] = useState({ visible: false });
Instead use this...
const [visible, setvisible] = useState(false);
Here setVisible is Hooks function not an object..
So you cannot set visible value by setVisible.visible = true.
Rather you should have you write this :
setVisible(true)
and Use visible variable as visible attribute of modal .
<Modal
...
visible={visible}
...
>

Related

Multiple Modal Opening when Updating a Row using React

I created a project using React and Bootstrap Table. Opening of modal is functional but unfortunately all the data in the table also opens their own modal.
So example I have 5 data in the table, when updating a row, the other four (4) modal also rendered and display.
The id of the data from Firestore is accessible to the child component (Edit_Modal.tsx) is there a way to add an id for the modal to make a reference to the data?
Manuscript.jsx
<tbody>
{thesisData.map((doc, index) => {
return (
<tr key={doc.id}>
<td>{index + 1}</td>
<td>{doc.title}</td>
<td>
{doc.members[0]}, {doc?.members[1]}
</td>
<td>{doc.adviser}</td>
<td>{doc.course}</td>
<td>{doc.pages}</td>
<td className="m-1 text-center">
<Button
className="mb-1"
variant="secondary"
onClick={(e) => openUpdateModal(doc.id, e)}
>
<IconContext.Provider value={{ color: "#fff" }}>
<div>
<BsFillPencilFill />
</div>
</IconContext.Provider>
{showModalEdit && <Edit_Modal modalToggle={doc.id} />}
</Button>
<Button
className="mb-1"
variant="danger"
onClick={(e) => deleteHandler(doc.id)}
>
<IconContext.Provider value={{ color: "#fff" }}>
<div>
<BsFillTrashFill />
</div>
</IconContext.Provider>
</Button>
</td>
</tr>
);
})}
</tbody>
openUpdateModal() function
const openUpdateModal = (id) => {
setThesisId(id);
setShowModalEdit(true);
};
Edit_Modal.tsx
const Edit_Modal = ({ modalToggle }) => {
//Use States for Modal
const [show, setShow] = useState(true);
const handleClose = () => {
setShow(!show);
};
return ReactDom.createPortal(
<div>
<Modal
show={show}
keyboard={false}
onHide={handleClose}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Update Thesis Details
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form
noValidate
validated={validated}
id="addFormId"
onSubmit={handleUpdateForm}
>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridTitle">
<Form.Label>Title</Form.Label>
<Form.Control
type="text"
onChange={(e) => setTitle(e.target.value)}
placeholder="Enter title"
value={title}
required
/>
<Form.Control.Feedback type="invalid">
Please enter a title.
</Form.Control.Feedback>
</Form.Group>
<Form.Group as={Col} controlId="formGridAdviser">
<Form.Label>Adviser</Form.Label>
<Form.Control
type="text"
onChange={(e) => setAdviser(e.target.value)}
placeholder="Name of Adviser"
value={adviser}
required
/>
<Form.Control.Feedback type="invalid">
Please enter an Adviser.
</Form.Control.Feedback>
</Form.Group>
</Row>
<Form.Group className="mb-3" controlId="formGridAbstract">
<Form.Label>Abstract</Form.Label>
<Form.Control
as="textarea"
onChange={(e) => setAbstract(e.target.value)}
rows={3}
placeholder="Enter Abstract Details"
value={abstract}
required
/>
<Form.Control.Feedback type="invalid">
Please enter Abstract Details.
</Form.Control.Feedback>
</Form.Group>
<Button type="Submit">Add Content</Button>
</Form>
</Modal.Body>
</Modal>
</div>,
document.getElementById("modal-root")
);
};
export default Edit_Modal;
As #adhinarayan said you can use the useState of setThesisId to get the specific ID of your document.
Example useState:
const [thesisId, setThesisId] = useState("");
You can use the openUpdateModal function to get the Modal and the thesis ID
const openUpdateModal = (id) => {
setThesisId(id); //useState for ID
setShowModalEdit(true); //useState for Modal
};
Finally, make sure that the Modal Component was placed outside of the map function to avoid looping of modals. You can set the thesisId to customized props of Edit_Modal
...</tbody>
</Table>
{showModalEdit && <Edit_Modal modalToggle={thesisId} />}
</Col>...

Cannot enter value into MDEditor

When I run the program, I can't enter a value in the input, help me
const FormCommnent = ({ onChange, onSubmit, value }) => (
<div className="form-comment">
<MDEditor
value={value}
onChange={onChange}
name="content"
rows={4}
autoFocus={0}
preview='edit'
/>
<MDEditor.Markdown source={value} />
<Button htmlType="submit" onClick={onSubmit} >
Add Comment
</Button>
</div>
);

React.js mdbottstrap show Modal with click

I would like to open a modal with a click. The button is visible on my page, but unfortunately the modal does not open when you click it.
Unfortunately I haven't found a solution yet how I can solve the problem.
function ModalPage(props) {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const [showModal, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<MDBContainer>
<MDBBtn rounded onClick={handleShow}>+</MDBBtn>
<MDBModal show={showModal} onHide={handleClose}>
<MDBModalHeader className="text-center" titleClass="w-100 font-weight-bold">Data Input</MDBModalHeader>
<MDBModalBody>
<form className="mx-3 grey-text">
<MDBInput label="ID" group type="text" validate />
<MDBInput label="Username" group type="email" validate error="wrong" success="right"
onChange={(evt) => setUsername(evt.target.value)}
/>
<MDBInput label="Password" group type="text"
onChange={(evt) => setPassword(evt.target.value)}
/>
<MDBInput type="textarea" rows="2" label="Your message" />
</form>
</MDBModalBody>
<MDBModalFooter className="justify-content-center">
<MDBBtn color="unique" onClick={handleClose}>Send
<MDBIcon far icon="paper-plane" className="ml-2" />
</MDBBtn>
</MDBModalFooter>
</MDBModal>
</MDBContainer>
);
}
export default withRouter(ModalPage);
According to this MDB page, the property used to dictate whether or not a modal is being shown is not show, but rather isOpen. Change
<MDBModal show={showModal} onHide={handleClose}>
To
<MDBModal isOpen={showModal} onHide={handleClose}>

React useState and map()

I'm trying to make an comment input from map,
but since I use the same useState all the input fields get changed.
How can I target a specific input?
return (
<div>
{posts.map(post => (
<div key={post.id}>
<img
src={`https://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`${post.id}`}
/>
<p>{post.description}</p>
<span>{post.likes ? post.likes : 0}</span>
<button onClick={() => like(post.id)}>Like</button>
<Link to={`/post/${post.id}`}>Edit</Link>
<button onClick={() => deletePost(post.id)}>Delete</button>
<form onSubmit={uploadComment}>
<input
type="text"
onChange={handleComment}
value={comment}
placeholder="Comment"
/>
</form>
</div>
))}
</div>
)
You have an own state per rendered post, which means that it is a use case for an own component:
function Post(post, deletePost) {
const [comment, setComment] = useState('');
const uploadComment = () => {}; // your code is missing
return (
<div key={post.id}>
<img
src={`https://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`${post.id}`}
/>
<p>{post.description}</p>
<span>{post.likes ? post.likes : 0}</span>
<button onClick={() => like(post.id)}>Like</button>
<Link to={`/post/${post.id}`}>Edit</Link>
<button onClick={() => deletePost(post.id)}>Delete</button>
<form onSubmit={uploadComment}>
<input
type="text"
onChange={e => setComment(e.target.value)}
value={comment}
placeholder="Comment"
/>
</form>
</div>
)
}
Then your render function would look like this:
return (
<div>
{posts.map(post => <Post post={post} deletePost={deletePost} />)}
</div>
)
Consider using react useState hook per input.

React Redux Form: form is submiting with old values

I have a FieldArray in Redux Form that I push objects inside this array and right after that I have a callback to trigger a function to make a POST request.
When I submit the form I get the old values, because the push() method of the Redux Form is an async dispach from redux.
// Parent component
<FieldArray
name="myObjects"
component={ChildComponent}
onSubmitObjects={this.onSubmit} />
// Function
onSubmit = async () => {
const { getFormValues } = this.props;
const data = {
myObjects: getFormValues.myObjects
}
try {
// const contact = await Service.updateUser(data);
} catch (e) {
console.log(e)
}
}
I need to submit the form with the new values added in the array right after the push method.
// Function inside ChildComponent
addNewObject = () => {
const { fields, onSubmitObjects} = this.props;
fields.push({
number: 1,
name: 'Foo',
});
if (onSubmitObjects) {
onSubmitObjects(); // cb() to trigger a function in the parent component
}
}
Is there a way to call the callback with the new values right after the push method?
You should use a form with redux-form handleSubmit to wrap your FieldArray. You can optionally pass your custom submit function (to make API requests, submit validation, etc.) to handleSubmit so it'd look like this <form onSubmit={handleSubmit(this.onSubmit)}> ...
See this example from redux-form official docs:
FieldArraysForm.js
import React from 'react'
import {Field, FieldArray, reduxForm} from 'redux-form'
import validate from './validate'
const renderField = ({input, label, type, meta: {touched, error}}) => (
<div>
<label>{label}</label>
<div>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
const renderHobbies = ({fields, meta: {error}}) => (
<ul>
<li>
<button type="button" onClick={() => fields.push()}>Add Hobby</button>
</li>
{fields.map((hobby, index) => (
<li key={index}>
<button
type="button"
title="Remove Hobby"
onClick={() => fields.remove(index)}
/>
<Field
name={hobby}
type="text"
component={renderField}
label={`Hobby #${index + 1}`}
/>
</li>
))}
{error && <li className="error">{error}</li>}
</ul>
)
const renderMembers = ({fields, meta: {error, submitFailed}}) => (
<ul>
<li>
<button type="button" onClick={() => fields.push({})}>Add Member</button>
{submitFailed && error && <span>{error}</span>}
</li>
{fields.map((member, index) => (
<li key={index}>
<button
type="button"
title="Remove Member"
onClick={() => fields.remove(index)}
/>
<h4>Member #{index + 1}</h4>
<Field
name={`${member}.firstName`}
type="text"
component={renderField}
label="First Name"
/>
<Field
name={`${member}.lastName`}
type="text"
component={renderField}
label="Last Name"
/>
<FieldArray name={`${member}.hobbies`} component={renderHobbies} />
</li>
))}
</ul>
)
const FieldArraysForm = props => {
const {handleSubmit, pristine, reset, submitting} = props
return (
<form onSubmit={handleSubmit}>
<Field
name="clubName"
type="text"
component={renderField}
label="Club Name"
/>
<FieldArray name="members" component={renderMembers} />
<div>
<button type="submit" disabled={submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'fieldArrays', // a unique identifier for this form
})(FieldArraysForm)

Categories