import React, { useState, useEffect } from "react";
import Axios from "axios";
import { Navigate, Link } from "react-router-dom";
import gravatarUrl from "gravatar-url";
import "../assets/css/profile.css";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import API from "../backend";
import { isAutheticated } from "../auth";
let img;
const Profile = () => {
// setting values
const [data, setData] = useState({
email: "",
name: "",
city: "",
state: "",
phone: "",
country: "",
role: "",
reg: "",
error: "",
success: "",
});
// state to know if someone clicked on the edit button
const [edit, setEdit] = useState(false);
// handaling onchange event
const onHandleChange = (val) => (event) => {
setUpdate({ ...update, [val]: event.target.value });
};
// Updating the new value from input
const [update, setUpdate] = useState({
name: "",
city: "",
state: "",
phone: "",
country: "",
error: "",
});
// state to check if someone click on submit
const [didSubmit, setDidSubmit] = useState(false);
// destructuring values from data (useState)
const { email, name, city, state, phone, country, reg, role } = data;
// destructuring token from localstorage
const { token } = isAutheticated();
// dataObject for api call
const dataType = {
headers: {
authorization: `Bearer ${token}`,
},
};
// get api call
const axiosGetCall = async () => {
try {
const res = await Axios.get(`${API}/user/profile`, dataType);
// seting image
img = gravatarUrl(res.data.user.email, { size: 200 });
// set data
setData({
...data,
email: res.data.user.email,
name: res.data.user.name,
city: res.data.user.city,
state: res.data.user.state,
phone: res.data.user.phone,
country: res.data.user.country,
role: res.data.user.role,
reg: res.data.user.createdAt,
success: true,
});
} catch (error) {
console.log(`error log: `, error);
setData({
...data,
error: error.response.data.error,
success: false,
});
}
};
// post call/update
const axiosUpdateCall = async () => {
// token
const { token1 } = isAutheticated();
// new dataObject for post call
const dataToken = {
headers: {
authorization: `Bearer ${token1}`,
},
};
try {
const res = await Axios.post(`${API}/user/profileEdit`, dataToken);
console.log(`res:`, res);
} catch (error) {
console.log(`error log: `, error);
setData({
...data,
error: error.response.data.error,
success: false,
});
}
};
// For get api call
useEffect(() => {
axiosGetCall();
}, []);
// for post api call if some clicked on submit
useEffect(() => {
if (didSubmit) {
axiosUpdateCall();
}
}, [didSubmit]);
// prevent default
const onSubmit = (event) => {
event.preventDefault();
setDidSubmit(true);
};
// Normal profile HTML CODE
const profileMain = () => {
return (
<div className="container bootdey flex-grow-1 container-p-y">
<div className="media align-items-center py-3 mb-3">
<img src={img} alt="" className="d-block ui-w-100 rounded-circle" />
<div className="media-body ml-4">
<h4 className="font-weight-bold mb-0">
{name.charAt(0).toUpperCase() + name.slice(1)}
</h4>
<button
onClick={() => {
setEdit(true);
}}
className="btn btn-primary btn-sm"
>
Edit
</button>
<Link to="" className="btn btn-primary btn-sm">
Go back
</Link>
</div>
</div>
<div className="card mb-4">
<div className="card-body">
<table className="table user-view-table m-0">
<tbody>
<tr>
<td>Registered:</td>
<td>{reg.slice(0, 10)}</td>
</tr>
<tr>
<td>Verified:</td>
<td>
<span className="fa fa-check text-primary"></span> No
</td>
</tr>
<tr>
<td>Role:</td>
<td>{role.charAt(0).toUpperCase() + role.slice(1)}</td>
</tr>
<tr>
<td>Status:</td>
<td>
<span className="badge badge-outline-success">Active</span>
</td>
</tr>
</tbody>
</table>
</div>
<hr className="border-light m-0" />
</div>
<div className="card">
<hr className="border-light m-0" />
<div className="card-body">
<h6 className="mt-4 mb-3">Personal Details:</h6>
<table className="table user-view-table m-0">
<tbody>
<tr>
<td>Full Name:</td>
<td>{name.charAt(0).toUpperCase() + name.slice(1)} </td>
<td></td>
</tr>
<tr>
<td>Email:</td>
<td>{email}</td>
</tr>
<tr>
<td>Phone:</td>
<td>{phone}</td>
</tr>
<tr>
<td>City:</td>
<td>{city}</td>
</tr>
<tr>
<td>State:</td>
<td>{state}</td>
</tr>
<tr>
<td>Country:</td>
<td>{country}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
);
};
// Profile when someone clicked on edit
const profileEdit = () => {
return (
<>
<div className="container bootdey flex-grow-1 container-p-y">
<div className="media align-items-center py-3 mb-3">
<img src={img} alt="" className="d-block ui-w-100 rounded-circle" />
<div className="media-body ml-4">
<h4 className="font-weight-bold mb-0">
{name.charAt(0).toUpperCase() + name.slice(1)}
</h4>
</div>
</div>
<div className="card mb-4">
<div className="card-body">
<table className="table user-view-table m-0">
<tbody>
<tr>
<td>Registered:</td>
<td>{reg.slice(0, 10)}</td>
</tr>
<tr>
<td>Verified:</td>
<td>
<span className="fa fa-check text-primary"></span>
No
</td>
</tr>
<tr>
<td>Role:</td>
<td>{role.charAt(0).toUpperCase() + role.slice(1)}</td>
</tr>
<tr>
<td>Status:</td>
<td>
<span className="badge badge-outline-success">
Active
</span>
</td>
</tr>
</tbody>
</table>
</div>
<hr className="border-light m-0" />
</div>
<div className="card">
<hr className="border-light m-0" />
<div className="card-body">
<h6 className="mt-4 mb-3">Personal Details:</h6>
<table className="table user-view-table m-0">
<tbody>
<tr>
<td>Full Name:</td>
<td>
<div className="col-3">
<input
type="text"
className="form-control"
onChange={onHandleChange("name")}
defaultValue={name}
/>
</div>
</td>
<td></td>
</tr>
<tr>
<td>Email:</td>
<td>{email}</td>
</tr>
<tr>
<td>Phone:</td>
<td>
<div className="col-3">
<input
type="text"
className="form-control"
onChange={onHandleChange("phone")}
defaultValue={phone}
/>
</div>
</td>
</tr>
<tr>
<td>City:</td>
<td>
<div className="col-3">
<input
type="text"
className="form-control"
onChange={onHandleChange("city")}
defaultValue={city}
/>
</div>
</td>
</tr>
<tr>
<td>State:</td>
<td>
<div className="col-3">
<input
type="text"
className="form-control"
onChange={onHandleChange("state")}
defaultValue={state}
/>
</div>
</td>
</tr>
<tr>
<td>Country:</td>
<td>
<div className="col-3">
<input
type="text"
className="form-control"
onChange={onHandleChange("country")}
defaultValue={country}
/>
</div>
</td>
</tr>
</tbody>
</table>
<button onClick={onSubmit} className="btn btn-primary btn-sm">
Submit
</button>
<button
onClick={() => {
setEdit(false);
}}
className="btn btn-primary btn-sm"
>
Cancel
</button>
</div>
</div>
</div>
</>
);
};
// toast to show error
const errorToast = () => {
toast(`${update.error}`, {
position: "top-right",
autoClose: false,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "dark",
});
};
return (
<>
<ToastContainer
position="top-right"
autoClose={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
theme="colored"
/>
{/* {error && (
<>
<Navigate to="/signout" />
</>
)} */}
{edit === true ? (
<>
{profileEdit()} <br />
</>
) : (
<>
{profileMain()} <br />
</>
)}
</>
);
};
export default Profile;
i'm calling two api calls..
get request and everything is working fine.
post request, here i'm unable to send the token to the backend..
i used same method for get request and it was working fine, but when used same method on post request i'm unable to send token..
is there something that i'm missing ?
i have added comment in each line of code.. my english is poor.
sorry and have a great day.
The second argument for Axios.post() is for the POST data and you're setting headers there. Pass an empty object (if you want to have empty POST data) and move your headers (dataToken) to the third argument:
const res = await Axios.post(`${API}/user/profileEdit`, {}, dataToken);
// ^set POST data here
From the documentation:
axios.post(url[, data[, config]])
Related
I have this code in PHP which has path "http://localhost:80/ico/vypsani.php"
$ico = $_POST['ico'];
include_once("core.php");
$sql = "SELECT * FROM ico WHERE ico = '$ico'";
$result = mysqli_query($conn, $sql);
$json_array = array();
while($row = mysqli_fetch_assoc($result)){
$json_array[]=$row;
}
echo json_encode($json_array);
in PHP I am searching row in database with input in React and its working, but I need to ge it into this table
import React,{useState, useEffect} from 'react';
const Data = () =>{
const [item, setItem] = useState([]);
useEffect(()=>{
fetch("http://localhost:80/ico/vypsani.php")
.then(res => res.json())
.then(
(result) => {
setItem(result);
}
)
},[])
return (
<div className="row">
<table class="table table-striped table-dark">
<thead className='thead-dark'>
<tr>
<th scope="col">ID</th>
<th scope="col">IČO</th>
<th scope="col">Název</th>
<th scope="col">Město</th>
<th scope="col">Ulice</th>
<th scope="col">Číslo Domovní</th>
<th scope="col">Číslo Orientační</th>
<th scope="col">Datum uložení</th>
</tr>
</thead>
<tbody>
{
item.map(item=>(
<tr key={item.ID}>
<td>{item.ID}</td>
<td>{item.ico}</td>
<td>{item.nazev}</td>
<td>{item.mesto}</td>
<td>{item.ulice}</td>
<td>{item.cisloDomovni}</td>
<td>{item.cisloOrientacni}</td>
<td>{item.datum}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}
but it shows the row from database like this and not in react table, I think because of the POST.
How react app looks like
import React from 'react';
import './App.css';
import Data from "./data/data.js";
function App() {
return (
<div className="App">
<form action='http://localhost:80/ico/vypsani.php' method="post">
<div className='form'>
<h1>IČO</h1>
<input name="ico" onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
alert("Zadávat lze pouze čísla")
}
}}
/>
<h1>Název firmy</h1>
<input name="nazev" type="text"></input>
<br></br>
<button type="submit" name='submit' value="vyhledat">Vyhledat</button>
<br></br>
<button type="submit" name='submit' value="odeslat">Odeslat</button>
<br></br>
</div>
<h1>Výpis z Databáze</h1>
<Data/>
</form>
</div>
);
}
export default App;
POSTing form to php page is not the correct way to do this. Please read answer to this question: Send a ReactJS form to a PHP page
To get your code to work, you can remove form in the html and handle the request using fetch only.
Also, change $ico = $_POST['ico']; to $ico = $_GET['ico']; in your php file
import React from 'react';
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
tableData: [],
ico: ''
};
}
handleInput = event => {
this.setState({ ico: event.target.value });
};
logValue = () => {
fetch("http://localhost:80/ico/vypsani.php?ico=" + this.state.ico)
.then(res => res.json())
.then(
(result) => {
this.setState(state => state.tableData = result);
}
)
.catch(err => {
throw err
});
};
render() {
return (
<div className="App">
<div className='form'>
<h1>IČO</h1>
<input name="ico" onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
alert("Zadávat lze pouze čísla")
}
}}
/>
<h1>Název firmy</h1>
<input name="nazev" onChange={this.handleInput} type="text"></input>
<br></br>
<button type="submit" name='submit' onClick={this.logValue} value="vyhledat">Vyhledat</button>
<br></br>
<button type="submit" name='submit' value="odeslat">Odeslat</button>
<br></br>
</div>
<h1>Výpis z Databáze</h1>
<div >
<table class="table table-striped table-dark">
<thead className='thead-dark'>
<tr>
<th scope="col">ID</th>
<th scope="col">IČO</th>
<th scope="col">Název</th>
<th scope="col">Město</th>
<th scope="col">Ulice</th>
<th scope="col">Číslo Domovní</th>
<th scope="col">Číslo Orientační</th>
<th scope="col">Datum uložení</th>
</tr>
</thead>
<tbody>
{
this.state.tableData.map(item => (
<tr key={item.ID}>
<td>{item.ID}</td>
<td>{item.ico}</td>
<td>{item.nazev}</td>
<td>{item.mesto}</td>
<td>{item.ulice}</td>
<td>{item.cisloDomovni}</td>
<td>{item.cisloOrientacni}</td>
<td>{item.datum}</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
);
}
}
export default Test;
Change your useEffect like this
useEffect(()=>{
fetch("http://localhost:80/ico/vypsani.php")
.then(result => {
setItem(result);
console.log(result);
}
)
.catch(error => {
console.log(error)
})
},[])
and table body like this
<tbody>
{
item && item?.map(ele=>(
<tr key={ele.ID}>
<td>{ele.ID}</td>
<td>{ele.ico}</td>
<td>{ele.nazev}</td>
<td>{ele.mesto}</td>
<td>{ele.ulice}</td>
<td>{ele.cisloDomovni}</td>
<td>{ele.cisloOrientacni}</td>
<td>{ele.datum}</td>
</tr>
))
}
</tbody>
I have an array of object that i got from my API and then displayed them to parent component as table row like so :
review.js
Each row has its own edit button where when i click ,it will popup a modal ( not redirecting to another page ) and it will contain some information based on which row i click.
Below is the example when i click the forth row which has "Mamang Racing" as the client name.
reviewDetailModal.js
The Problem is , on the children component (modal component) when i about to edit any other rows for some reason it will still show me the latest data ( in this case the forth row ).
Code is shown below :
review.js
const Review = () => {
const [showModal, setShowModal] = useState("close");
const [review, setReview] = useState([]);
const handleClose = () => setShowModal("close");
const handleShowModalOne = () => setShowModal("modal-one");
const handleShowModalTwo = () => setShowModal("modal-two");
useEffect(() => {
let isMounted = false;
const FetchReview = async () => {
await publicAxios
.get("/api/review/")
.then((result) => {
setReview(result.data);
})
.catch((err) => console.log(err));
};
FetchReview();
console.log(review);
return () => {
isMounted = true;
};
}, []);
return (
<Layout>
<Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
<div className="d-flex flex-row-reverse">
<Button
variant="success"
className="mb-2"
onClick={handleShowModalOne}
>
<FaPlusCircle /> Add Testimonial
</Button>
<AddReviewModal isShow={showModal} isClose={handleClose} />
</div>
<Table striped bordered hover className="text-center">
<thead>
<tr>
<th>Client</th>
<th>Review</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{review.map((item) => (
<tr key={item._id}>
<td className="align-middle">{item.clientName}</td>
<td className="align-middle">{item.projectName} </td>
<td style={{ width: "200px" }} className="align-middle">
<Button variant="primary" className="m-1 ">
<FaEye />
</Button>
<Button
variant="warning"
className="m-1"
onClick={handleShowModalTwo}
>
<FaPenSquare />
</Button>
<ReviewDetailModal
data={item}
isShow={showModal}
isClose={handleClose}
/>
<Button variant="danger" className="m-1">
<FaTrashAlt />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Container>
</Layout>
);
};
reviewDetailModal.js
const ReviewDetailModal = ({ data, isShow, isClose }) => {
return (
<Modal show={isShow === "modal-two"} onHide={isClose}>
<Modal.Header>
<Modal.Title>Edit Review</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="form.InputName">
<Form.Label>Your Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.clientName}
/>
</Form.Group>
<Form.Group controlId="form.InputName">
<Form.Label>Project Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.projectName}
/>
</Form.Group>
<Form.Group controlId="form.Rating">
<Form.Label>Tinggalkan Rating : </Form.Label>
<Form.Control as="select" defaultValue={data.rating}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Form.Control>
</Form.Group>
<Form.Group controlId="form.TextArea">
<Form.Label>Kalimat Review</Form.Label>
<Form.Control
as="textarea"
rows={3}
defaultValue={data.description}
/>
</Form.Group>
<Form.Group>
<label>Foto Anda</label>
<Form.File id="pictureFile" />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={isClose}>Close</Button>
</Modal.Footer>
</Modal>
);
};
API Result , one of my data :
Array(4) [ {…}, {…}, {…}, {…} ]
0: Object { _id: "60c18f1de4579e22d0e636cb", clientName: "pak dwek", projectName: "Landing Page Pakdwek", … }
__v: 0
_id: "60c18f1de4579e22d0e636cb"
clientName: "pak dwek"
createdAt: "2021-06-10T04:03:41.594Z"
description: "Sangat Baik , pelayanan memuaskan"
photo: "img/pakdhe.jpg"
projectName: "Landing Page Pakdwek"
score: 5
updatedAt: "2021-06-10T04:03:41.594Z"
<prototype>: Object { … }
1: Object { _id: "60c34afac1bdda333840a1cb", clientName: "alex", projectName: "landing page alex", … }
__v: 0
_id: "60c34afac1bdda333840a1cb"
clientName: "alex"
createdAt: "2021-06-11T11:37:30.852Z"
description: "sangat baik"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411449/review-photos/ipbqv8xxqfs45yx9s5kz.jpg"
projectName: "landing page alex"
rating: 4
updatedAt: "2021-06-11T11:37:30.852Z"
<prototype>: Object { … }
2: Object { _id: "60c34b7ec1bdda333840a1cc", clientName: "Suhardono", projectName: "Project Web APp", … }
__v: 0
_id: "60c34b7ec1bdda333840a1cc"
clientName: "Suhardono"
createdAt: "2021-06-11T11:39:42.456Z"
description: "buruk"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411581/review-photos/hkxt98hm28sb6sgc3wao.jpg"
projectName: "Project Web APp"
rating: 2
updatedAt: "2021-06-11T11:39:42.456Z"
<prototype>: Object { … }
3: Object { _id: "60c6d7a5eca83317bc8d0c5c", clientName: "Mamang Racing", projectName: "Test Project", … }
__v: 0
_id: "60c6d7a5eca83317bc8d0c5c"
clientName: "Mamang Racing"
createdAt: "2021-06-14T04:14:29.910Z"
description: "Bagusssss"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623644068/review-photos/sdha9mu1r6a3jvjfbqpm.png"
projectName: "Test Project"
rating: 3
updatedAt: "2021-06-14T04:14:29.910Z"
<prototype>: Object { … }
length: 4
You have to create a save method & pass the modal data through that save method to Review component.
review.js
const Review = () => {
const [showModal, setShowModal] = useState("close");
const [review, setReview] = useState([]);
const handleClose = () => setShowModal("close");
const handleShowModalOne = () => setShowModal("modal-one");
const handleShowModalTwo = () => setShowModal("modal-two");
useEffect(() => {
let isMounted = false;
const FetchReview = async () => {
await publicAxios
.get("/api/review/")
.then((result) => {
setReview(result.data);
})
.catch((err) => console.log(err));
};
FetchReview();
console.log(review);
return () => {
isMounted = true;
};
}, []);
const onChangeReview = (index, obj) => {
setReview((prev) =>
prev.map((item, i) => (i === index ? { ...item, ...obj } : item))
);
}; // Update the state using the modal submitted data
return (
<Layout>
<Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
<div className="d-flex flex-row-reverse">
<Button
variant="success"
className="mb-2"
onClick={handleShowModalOne}
>
<FaPlusCircle /> Add Testimonial
</Button>
<AddReviewModal isShow={showModal} isClose={handleClose} />
</div>
<Table striped bordered hover className="text-center">
<thead>
<tr>
<th>Client</th>
<th>Review</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{review.map((item, index) => (
<tr key={item._id}>
<td className="align-middle">{item.clientName}</td>
<td className="align-middle">{item.projectName} </td>
<td style={{ width: "200px" }} className="align-middle">
<Button variant="primary" className="m-1 ">
<FaEye />
</Button>
<Button
variant="warning"
className="m-1"
onClick={handleShowModalTwo}
>
<FaPenSquare />
</Button>
<ReviewDetailModal
index={index} {/* Pass the index of the item */}
data={item}
isShow={showModal}
isClose={handleClose}
onChangeReview={onChangeReview} {/* Pass the handler as an prop */}
/>
<Button variant="danger" className="m-1">
<FaTrashAlt />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Container>
</Layout>
);
};
reviewDetailModal.js
const ReviewDetailModal = ({
index,
data,
isShow,
isClose,
onChangeReview
}) => {
const name = useRef(null);
const project = useRef(null);
const rate = useRef(null);
const review = useRef(null);
const picture = useRef(null); // Creating references to Modal form fields
const onSave = () => {
onChangeReview(index, {
clientName: name.current.value,
projectName: project.current.value,
score: rate.current.value,
review: review.current.value, // review info not exist in API returned array
photo: picture.current.value
});
}; // Model data save handler
return (
<Modal show={isShow === "modal-two"} onHide={isClose}>
<Modal.Header>
<Modal.Title>Edit Review</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="form.InputName">
<Form.Label>Your Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.clientName}
ref={name} {/* Pass the references to the the form fields */}
/>
</Form.Group>
<Form.Group controlId="form.InputName">
<Form.Label>Project Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.projectName}
ref={project}
/>
</Form.Group>
<Form.Group controlId="form.Rating">
<Form.Label>Tinggalkan Rating : </Form.Label>
<Form.Control as="select" defaultValue={data.rating} ref={rate}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Form.Control>
</Form.Group>
<Form.Group controlId="form.TextArea">
<Form.Label>Kalimat Review</Form.Label>
<Form.Control
as="textarea"
rows={3}
defaultValue={data.description}
ref={review}
/>
</Form.Group>
<Form.Group>
<label>Foto Anda</label>
<Form.File id="pictureFile" ref={picture} />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={onSave}>Save</Button>{" "}
{/* Add the Save handler to onClick */}
<Button onClick={isClose}>Close</Button>
</Modal.Footer>
</Modal>
);
};
Let me know if you need further support.
Try this approach,
Update the selected record info in the local state and pass that info into the model.
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Modal, Button } from "react-bootstrap";
const data = [
{
id: 1001,
firstname: "Mark",
lastname: "Otto",
age: 34,
location: "London",
address: "10 Downing Street"
},
{
id: 1002,
firstname: "Jacob",
lastname: "Snow",
age: 34,
location: "India",
address: "#110 broad Street"
},
{
id: 1003,
firstname: "Sarun",
lastname: "U K",
age: 30,
location: "USA",
address: "#1 NY"
}
];
function App() {
const [show, setShow] = useState(false);
const [selectedData, setSelectedData] = useState({});
const hanldeClick = (selectedRec) => {
setSelectedData(selectedRec);
setShow(true);
};
const hideModal = () => {
setShow(false);
};
return (
<div className="App">
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Location</th>
<th scope="col">Show More</th>
</tr>
</thead>
<tbody>
{data.map((v) => (
<tr>
<td>{v.id}</td>
<td>{v.firstname}</td>
<td>{v.lastname}</td>
<td>#{v.location}</td>
<td>
<a href="#" onClick={() => hanldeClick(v)}>
More details
</a>
</td>
</tr>
))}
</tbody>
</table>
<Dialog show={show} details={selectedData} handleClose={hideModal} />
</div>
);
}
const Dialog = ({ show, handleClose, details }) => {
return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>
{details?.firstname} {details?.lastname}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Age</th>
<th scope="col">Location</th>
<th scope="col">Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>{details?.id}</td>
<td>{details?.firstname}</td>
<td>{details?.lastname}</td>
<td>{details?.age}</td>
<td>{details?.location}</td>
<td>{details?.address}</td>
</tr>
</tbody>
</table>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
);
};
export default App;
Sample codesandbox - https://codesandbox.io/s/react-model-dialog-box-askavy-forked-7uf94?file=/src/App.js:0-2922
I am new to React and I don't know how to overcome the below situation.
Let say I have to display a table.In Table <td> i have one dropdown which I got from my child component.And also have some <div> next to the dropdown.
So,for each dropdown change, i have to bind some html into that <div>.Below line is working for very first dropdown change.
ReactDOM.render(myHtml, document.getElementById(myID));
So For a second time it is not render the new html.
Kindly correct me If I did anything wrong and give me some suggestion to overcome the above issue.
Thanks in Advance.
class Home extends Component{
state = {
tableDetails:'',
};
LoadTableDetails = () => {
const getUrl = "Some API Url";
let dd= fetch(getUrl);
dd.then(response => {
return response.json();
}).then(items => {
var body = this.getTableBody(items);
this.setTableDetails(body);
});
}
getTableBody(items){
let body ;
if(items != null){
body = items.map((folder,index) =>
<tr key={index}>
<td>{folder.FolderName}</td>
<td>
<MyDropDown fileNames={folder.FileNames} folderFiles={folder.FolderFiles} id={folder.FolderName.replace(/ /g,'_')} setSelectedFile = {this.setSelectedFile}/> // Here I get dropdown selected value and see setSelectedFile method
</td>
<td>
<div id={folder.FolderName.replace(/ /g,'_')}>
////I need some html here based on the above dropdown change
</div>
</td>
<td></td>
</tr>
);
}
return folderItems;
}
setTableDetails(body){
let dd = (<div className="container" >
<h2 class="text-center">Server Details</h2>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Folder</th>
<th scope="col">Config Files</th>
<th scope="col">Config Section</th>
<th scope="col">App Settings</th>
</tr>
</thead>
<tbody>
{body}
</tbody>
</table>
</div>);
this.setState({tableDetails:dd});
}
setSelectedFile = (val) =>{
const getUrl = 'my url';
let loadItems = fetch(getUrl);
loadItems.then(response=>{
return response.json();
}).then(data=>{
let configHtml = (
<div>
<MyDropDown fileNames={data} id={val.id + path.replace('\\','_').replace('/\//g','_')} path={path} setSelectedFile = {this.getConfigSectionDetails}/>
<div className="mt-4" id={val.id + path.replace('\\','_').replace('/\//g','_')}>
</div>
</div>
);
let id = val.id; //This is the id where my new
ReactDOM.render(configHtml, document.getElementById(id)); //this line is working for my first dropdown change.If I change the dropdown again then it is not rerenered
});
}
render(){
return (
<div class="mt-4">
<div class="input-group-append">
<button class="btn btn-info" type="button" onClick={this.LoadTableDetails}>Load Table Details</button>
</div>
{this.state.tableDetails}
</div>
);
}
}
export default Home;
I got my Answer.We have to use our states to update the values and not html.
class Home extends Component{
state = {
tableDetails:'',
dropdownDetails:''
};
LoadTableDetails = () => {
const getUrl = "Some API Url";
let dd= fetch(getUrl);
dd.then(response => {
return response.json();
}).then(items => {
this.setState({
tableDetails:items
});
});
}
getTableDetails = (items)=>{
return (<div className="container" >
<h2 class="text-center">Server Details</h2>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Folder</th>
<th scope="col">Config Files</th>
<th scope="col">Config Section</th>
<th scope="col">App Settings</th>
</tr>
</thead>
<tbody>
{
items.map((folder,index) =>{
return (<tr key={index}>
<td>{folder.FolderName}</td>
<td>
<MyDropDown fileNames={folder.FileNames} folderFiles={folder.FolderFiles} id=index setSelectedFile ={this.setSelectedFile}/>
</td>
<td>
<div>
{this.getConfigHtml(this.state.dropdownDetails)}
</div>
</td>
<td></td>
</tr>)
})
}
</tbody>
</table>
</div>);
}
getConfigHtml =(val)=>{
return (
<div>
<MyDropDown fileNames={val.data} path={val.path} setSelectedFile = {this.getConfigSectionDetails}/>
</div>
);
}
setSelectedFile = (val) =>{
const getUrl = 'my url';
let loadItems = fetch(getUrl);
loadItems.then(response=>{
return response.json();
}).then(data=>{
let val={
data:data,
path:val.path
};
this.setState({dropdownDetails:val});
});
}
render(){
return (
<div class="mt-4">
<div class="input-group-append">
<button class="btn btn-info" type="button" onClick={this.LoadTableDetails}>Load Table Details</button>
</div>
{this.getTableDetails(this.state.tableDetails)}
</div>
);
}
}
export default Home;
I am doing a call for an API (fake, just for testing), but i recive an error when calling it
This is my code of the call
class Pacientes extends React.Component {
state = {
loading: true,
error: null,
data: undefined,
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
this.setState({ loading: true, error: null });
try {
const data = await api.pacientes.list();
this.setState({ loading: false, data: data });
} catch (error) {
this.setState({ loading: false, error: error });
}
};
render() {
if (this.state.loading === true && !this.state.data)
return (
<PageLoading/>
);
if (this.state.error) return (
`Este fue el error ${this.state.error}`
);
return (
<React.Fragment>
<TableHeader elementos={this.state.data} />
<Table pacientes={this.state.data} />
</React.Fragment>
);
}
}
And the console says than the error is on the following line :
this.setState({ loading: false, data: data });
But I think than there is not.
Then of make the call of the api i call a component and give props of the answer of the api(Data), and this is the component:
function useSearchPacientes(pacientes) {
const [query, setQuery] = React.useState('');
const [filteredPacientes, setFilteredPacientes] = React.useState(pacientes);
React.useMemo(() => {
const result = pacientes.filter(paciente => {
return (
`${paciente.firstName} ${paciente.lastName}`
)
.toLowerCase()
.includes(query.toLowerCase());
});
setFilteredPacientes(result);
}, [pacientes, query]);
return { query, setQuery, filteredPacientes };
}
function Table(props) {
const pacientes = props.pacientes;
const { query, setQuery, filteredPacientes } = useSearchPacientes(pacientes);
if (filteredPacientes.length === 0) {
return (
"No se encontraron resultados"
);
return (
<React.Fragment>
<div className="search-container">
<form className="search-input-container">
<input type="text" className="search-input form-control" placeholder="Buscar"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
<FontAwesomeIcon icon={faSearch} className="text-muted search-input-icon"/>
</form>
<div className="options">
<select name="" className="form-control" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</div>
</div>
<br />
<div className="row justify-content-center">
<div className="col-10 table-container border-primary">
<br />
<table className="table rounded table-responsive-md">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Nombre</th>
<th scope="col">Apellido</th>
<th scope="col">Twitter</th>
<th scope="col" className="text-center">
Opciones
</th>
</tr>
</thead>
<tbody>
{filteredPacientes.map(paciente => {
return (
<tr key={paciente.id}>
<TableRow paciente={paciente} />
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<br />
</React.Fragment>
);
}
}
So, then of serch this error, i cant found a real solution, but i really think than the error is in the second component, near of the map function to the array.
You have wrongly used closing curly bracket for your if condition
function Table(props) {
const pacientes = props.pacientes;
const { query, setQuery, filteredPacientes } = useSearchPacientes(pacientes);
if (filteredPacientes.length === 0) {
return (
"No se encontraron resultados"
);
} // the closing bracket should be here
return (
<React.Fragment>
<div className="search-container">
<form className="search-input-container">
<input type="text" className="search-input form-control" placeholder="Buscar"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
<FontAwesomeIcon icon={faSearch} className="text-muted search-input-icon"/>
</form>
<div className="options">
<select name="" className="form-control" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</div>
</div>
<br />
<div className="row justify-content-center">
<div className="col-10 table-container border-primary">
<br />
<table className="table rounded table-responsive-md">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Nombre</th>
<th scope="col">Apellido</th>
<th scope="col">Twitter</th>
<th scope="col" className="text-center">
Opciones
</th>
</tr>
</thead>
<tbody>
{filteredPacientes.map(paciente => {
return (
<tr key={paciente.id}>
<TableRow paciente={paciente} />
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<br />
</React.Fragment>
);
}
I m learning of angular js and i have found i issue .
I m creating a new projects .
i have some button edit , add, remove,
if i click to my edit button than show all field but i want to show only current field than i click to update update this filed .
My code is here
Anguar
var app = angular.module('addApp', []);
app.controller('modifyCtrl', ['$scope', function($scope){
$scope.tabelsData= [
{'name':'rohit', 'dob':'15-august-1985', 'emailId':'rohit#rohit.com', 'phone':'9999999999', 'address':'Delhi Rohini', 'id':'0' },
{'name':'aman', 'dob':'26-july-1975', 'emailId':'haryanat#hr.com', 'phone':'9874563210', 'address':'Haryana Sonepat', 'id':'1' },
{'name':'devraj', 'dob':'27-march-1980', 'emailId':'punjab#punjab.com', 'phone':'7410258963', 'address':'Punjab AmritSar', 'id':'2' }
];
$scope.modify = function(tableData){
$scope.modifyField = true;
$scope.viewField = true;
};
$scope.update = function(tableData){
$scope.modifyField = false;
$scope.viewField = false;
};
}]);
HTML Code is
<div ng-app="addApp">
<div class="wraper" ng-controller="modifyCtrl">
<table>
<thead>
<tr>
<th>Name:</th>
<th>Date Of Birth</th>
<th>Email Id</th>
<th>Phone No.</th>
<th>Address</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tableData in tabelsData"><form>
<td>
<div ng-hide="viewField">{{tableData.name | uppercase}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.name" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.dob}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.dob" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.emailId}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.emailId" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.phone}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.phone" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.address}}</div>
<div ng-show="modifyField">
<textarea ng-model="tableData.address"></textarea>
</div>
</td>
<td>
<button ng-hide="viewField" ng-click="modify(tableData)">Modify</button>
<button ng-show="modifyField" ng-click="update(tableData)">Update</button>
<button ng-hide="viewField">Add</button>
<button ng-hide="viewField">Remove</button>
</td></form>
</tr>
</tbody>
</table>
</div>
</div>
var app = angular.module('addApp', []);
app.controller('modifyCtrl', ['$scope', function($scope){
$scope.tabelsData= [
{'name':'rohit', 'dob':'15-august-1985', 'emailId':'rohit#rohit.com', 'phone':'9999999999', 'address':'Delhi Rohini', 'id':'0' },
{'name':'aman', 'dob':'26-july-1975', 'emailId':'haryanat#hr.com', 'phone':'9874563210', 'address':'Haryana Sonepat', 'id':'1' },
{'name':'devraj', 'dob':'27-march-1980', 'emailId':'punjab#punjab.com', 'phone':'7410258963', 'address':'Punjab AmritSar', 'id':'2' }
];
$scope.modify = function(tableData){
$scope.modifyField = true;
$scope.viewField = true;
};
$scope.update = function(tableData){
$scope.modifyField = false;
$scope.viewField = false;
};
}]);
table td, table th{
border:solid 1px red;
padding:5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="addApp">
<div class="wraper" ng-controller="modifyCtrl">
<table>
<thead>
<tr>
<th>Name:</th>
<th>Date Of Birth</th>
<th>Email Id</th>
<th>Phone No.</th>
<th>Address</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tableData in tabelsData"><form>
<td>
<div ng-hide="viewField">{{tableData.name | uppercase}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.name" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.dob}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.dob" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.emailId}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.emailId" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.phone}}</div>
<div ng-show="modifyField"><input type="text" ng-model="tableData.phone" /></div>
</td>
<td>
<div ng-hide="viewField">{{tableData.address}}</div>
<div ng-show="modifyField">
<textarea ng-model="tableData.address"></textarea>
</div>
</td>
<td>
<button ng-hide="viewField" ng-click="modify(tableData)">Modify</button>
<button ng-show="modifyField" ng-click="update(tableData)">Update</button>
<button ng-hide="viewField">Add</button>
<button ng-hide="viewField">Remove</button>
</td></form>
</tr>
</tbody>
</table>
</div>
</div>
If you only want one row to show the inputs on clicking its respective modify button you have two options:
1) Attach booleans to each of the JSON indexes of the tabelsData array.
2) Make a mirror array that houses these booleans.
Having two separate booleans in this case is useless, because each one is being treated on a toggle basis:
Here is the core code for doing approach number two since I assume you want your data to remain the same:
JS:
$scope.editingData = {};
for (var i = 0, length = $scope.tabelsData.length; i < length; i++) {
$scope.editingData[$scope.tabelsData[i].id] = false;
}
$scope.modify = function(tableData){
$scope.editingData[tableData.id] = true;
};
$scope.update = function(tableData){
$scope.editingData[tableData.id] = false;
};
Html:
<tbody>
<tr ng-repeat="tableData in tabelsData">
<td>
<div ng-hide="editingData[tableData.id]">{{tableData.name | uppercase}}</div>
<div ng-show="editingData[tableData.id]"><input type="text" ng-model="tableData.name" /></div>
</td>
<td>
<div ng-hide="editingData[tableData.id]">{{tableData.dob}}</div>
<div ng-show="editingData[tableData.id]"><input type="text" ng-model="tableData.dob" /></div>
</td>
<td>
<div ng-hide="editingData[tableData.id]">{{tableData.emailId}}</div>
<div ng-show="editingData[tableData.id]"><input type="text" ng-model="tableData.emailId" /></div>
</td>
<td>
<div ng-hide="editingData[tableData.id]">{{tableData.phone}}</div>
<div ng-show="editingData[tableData.id]"><input type="text" ng-model="tableData.phone" /></div>
</td>
<td>
<div ng-hide="editingData[tableData.id]">{{tableData.address}}</div>
<div ng-show="editingData[tableData.id]">
<textarea ng-model="tableData.address"></textarea>
</div>
</td>
<td>
<button ng-hide="editingData[tableData.id]" ng-click="modify(tableData)">Modify</button>
<button ng-show="editingData[tableData.id]" ng-click="update(tableData)">Update</button>
<button ng-hide="viewField">Add</button>
<button ng-hide="viewField">Remove</button>
</td>
</tr>
</tbody>
I made an example:
http://plnkr.co/edit/lXq1WB
Here is an example in Angular2, (this will NOT work for AngularJS!)
fichier.html:
<ng2-toasty [position]="'top-left'"></ng2-toasty>
<label for="trainingInput" class="mr-2">{{ 'LABEL.FORMATION' | translate }} :</label>
<table class="table table-hover table-striped table-sortable table-bordered">
<thead>
<tr>
<th *ngFor="let column of columns" [class]="selectedClass(column.variable)" (click)="changeSorting(column.variable)" translate>
{{column.display}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let object of data | orderBy : convertSorting(); let rowIndex = index">
<td *ngFor="let column of columns" class="{{column.variable}}-td">
<div *ngIf="!toUpdates[object['id']]" >{{object[column.variable] | format: column.filter}}</div>
<div *ngIf="toUpdates[object['id']]"><input type="text" [(ngModel)]="object[column.variable]" ></div>
</td>
<td class="text-center">
<i *ngIf="!toUpdates[object['id']]" class="fa fa-pencil-square-o edit-formation" aria-hidden="true" (click) = "editFormation(object)"></i>
<i *ngIf="toUpdates[object['id']]" class="fa fa-check-square-o save-edit-form" (click)="updateFormation(object)"></i>
<i class="fa fa-times" aria-hidden="true" (click)="deleteFormation(object['id'])"></i>
</td>
</tr>
<tr [hidden]="isDisabled()">
<td><input type="text" class="form-control" placeholder="Année" #years></td>
<td><input type="text" class="form-control" placeholder="Formation" #label></td>
<td><input type="text" class="form-control" placeholder="Durée" #duration></td>
<td class="text-center align-middle">
<i class="fa fa-plus-circle fa-2x" (click)="addFormation(years.value, label.value, duration.value)"></i>
</td>
</tr>
</tbody>
</table>
fichier.ts:
import {Component, Injector, Input, OnChanges, OnInit} from '#angular/core';
import { Http, Headers, RequestOptions, URLSearchParams } from '#angular/http';
import DynamicComponent from '../dynamic-component';
import Formation from './formation';
import {ToastyService, ToastyConfig, ToastOptions, ToastData} from 'ng2-toasty';
#Component({
moduleId: module.id,
selector: 'formations-selector',
templateUrl: './formations-template.html',
styleUrls: ['./formations-template.css'],
})
export default class FormationsComponent{
candidate: any = null;
listFormations: any = null;
candidateDetails: any = null;
columns: any[];
sort: any;
data: any[];
toUpdates: {};
constructor(private injector: Injector, private http: Http,private toastyService: ToastyService, private toastyConfig: ToastyConfig) {
this.candidateDetails = this.injector.get('candidateDetails');
this.candidate = this.candidateDetails.candidate;
this.listFormations = this.candidateDetails.listFormations;
this.columns = this.listFormations.columns;
this.sort = this.listFormations.sort;
this.data = this.listFormations.data;
this.toastyConfig.theme = 'material';
this.toUpdates = {};
}
ngAfterViewInit(){
$(document).ready(function() {
/*
$('.edit-formation').click(function () {
var dad = $(this).parent().parent();
dad.find('td .duration-span').hide();
dad.find('td.duration-td').append('<input type="text" class="form-control" placeholder="Durée" value="'+dad.find('td .duration-span').html()+'" id = "duration-update" #durationu>');
dad.find('td .label-span').hide();
dad.find('td.label-td').append('<input type="text" class="form-control" placeholder="Formation" id="label-update" value="'+dad.find('td .label-span').html()+'" #labelu>');
dad.find('td .years-span').hide();
dad.find('td.years-td').append('<input type="text" class="form-control" placeholder="Année" id="years-update" value="'+dad.find('td .years-span').html()+'" #yearsu>');
dad.find('td.years-td').append('<i class="fa fa-check-square-o save-edit-form hidden" (click)="updateFormation(1, years.value, label.value, durationu)"></i>');
dad.find('td .edit-formation').addClass("hidden");
dad.find('td .save-edit-form').removeClass("hidden");
});
*/
/*
$('.save-edit-form').click(function () {
var dad = $(this).parent().parent();
dad.find('td .save-edit-form').addClass("hidden");
dad.find('td .edit-formation ').removeClass("hidden");
dad.find('td .duration-span').show();
$('#duration-update').remove();
dad.find('td .label-span').show();
$('#label-update').remove();
dad.find('td .years-span').show();
$('#years-update').remove();
});
*/
});
}
//Action déclenché lors d'un changement de société du candidat : on met à jour la liste des métiers associés
onChangeCompaniesInput(value) {
}
isDisabled(isDisabled) {
//return (isDisabled || !this.candidateDetails.isUserAuthorized) ? true : false;
}
selectedClass(columnName): string{
return columnName == this.sort.column ? 'sort-' + this.sort.descending : '';
}
changeSorting(columnName): void{
var sort = this.sort;
if (sort.column == columnName) {
sort.descending = !sort.descending;
} else {
sort.column = columnName;
sort.descending = false;
}
}
convertSorting(): string{
return this.sort.descending ? '-' + this.sort.column : this.sort.column;
}
onChangeMainFormaion(value): void{
console.log(value);
}
deleteFormation(idFormation): void{
let headers = new Headers('Content-Type', 'application/json');
let params: URLSearchParams = new URLSearchParams();
this.http.post('/api/formations/'+idFormation+'/deleteFormation', params).toPromise()
.then(
res =>
{
if(res.status == 200){
this.toastyService.success({
title: "Success",
msg: "La formation a etait supprmié avec Succès",
showClose: true,
timeout: 5000,
theme: 'default',
});
}else{
this.toastyService.error({
title: "Error",
msg: "Une erreur est survenue, veuillez réessayer ultérieurement",
showClose: true,
timeout: 5000,
theme: 'default',
});
}
}
).catch(this.handleError);
}
editFormation(tableData): void{
this.toUpdates[tableData['id']]= true;
}
updateFormation(tableData): void {
this.toUpdates[tableData['id']]= false;
console.log(tableData);
}
addFormation(years: string, label: string, durration: string, main: boolean = false): void{
let headers = new Headers('Content-Type', 'application/json');
let params: URLSearchParams = new URLSearchParams();
params.append('years', years);
params.append('label', label);
params.append('durration', durration);
params.append('main', main);
//let formation = new Formation(years, label, durration, false);
return this.http.post('/api/formations/'+this.candidate.id+'/addFormation', params).toPromise()
.then(
res =>
{
if(res.status == 200){
this.toastyService.success({
title: "Success",
msg: "La formation a etait ajouter avec Succès",
showClose: true,
timeout: 5000,
theme: 'default',
});
}else{
this.toastyService.error({
title: "Error",
msg: "Une erreur est survenue, veuillez réessayer ultérieurement",
showClose: true,
timeout: 5000,
theme: 'default',
});
}
}
).catch(this.handleError);
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Promise.reject(errMsg);
}
}