i have create the simple crud system in React with Laravel. i shall be able to add the records and view the records but couldn't update the records. what i tried so far i attached below. i attached the full code for easy for understanding. i think the problem is occur in the update url is there any error. Api i tested through the console it is working well in update part
i attached the when i looked at the console
127.0.0.1:8000/api/update/undefined:1
Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
Full code
import axios from 'axios';
import {useEffect, useState } from "react";
function EmployeeLoad()
{
const [id, setId] = useState('');
const [name, setName] = useState("");
const [address, setAddress] = useState("");
const [mobile, setMobile] = useState("");
const [users, setUsers] = useState([]);
useEffect(()=>
{
Load();
},[])
async function Load()
{
const result = await axios.get(
"http://127.0.0.1:8000/api/employees");
setUsers(result.data);
console.log(result.data);
}
async function save(event)
{
event.preventDefault();
try
{
await axios.post("http://127.0.0.1:8000/api/save",
{
name: name,
address: address,
mobile: mobile
});
alert("Employee Registation Successfully");
setId("");
setName("");
setAddress("");
setMobile("");
}
catch(err)
{
alert("User Registation Failed");
}
}
async function editEmployee(users)
{
setName(users.name);
setAddress(users.address);
setMobile(users.mobile);
setId(users.id);
}
async function update(event)
{
event.preventDefault();
try
{
await axios.patch("http://127.0.0.1:8000/api/update/"+ users.id,
{
id: id,
name: name,
address: address,
mobile: mobile
});
alert("Employee Registation Successfully");
setId("");
setName("");
setAddress("");
setMobile("");
}
catch(err)
{
alert("User Registation Failed");
}
}
return (
<div>
<h1>Employee Details</h1>
<div class="container mt-4" >
<form>
<div class="form-group">
<input type="text" class="form-control" id="employee_id"
value={id}
onChange={(event) =>
{
setId(event.target.value);
}}
/>
<label>employeeName</label>
<input type="text" class="form-control" id="employeeName"
value={name}
onChange={(event) =>
{
setName(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>employeeAddress</label>
<input type="text" class="form-control" id="employeeAddress"
value={address}
onChange={(event) =>
{
setAddress(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>Mobile</label>
<input type="text" class="form-control" id="employeeMobile"
value={mobile}
onChange={(event) =>
{
setMobile(event.target.value);
}}
/>
</div>
<div>
<button class="btn btn-primary mt-4" onClick={save}>Register</button>
<button class="btn btn-primary mt-4" onClick={update}>Update</button>
</div>
</form>
</div>
<table class="table table-dark" align="center">
<thead>
<tr>
<th scope="col">Employee Id</th>
<th scope="col">Employee Name</th>
<th scope="col">Employee Address</th>
<th scope="col">Employee Mobile</th>
<th scope="col">Option</th>
</tr>
</thead>
{users.map(function fn(item)
{
return(
<tbody>
<tr>
<th scope="row">{item.id} </th>
<td>{item.name}</td>
<td>{item.address}</td>
<td>{item.mobile}</td>
<td>
<button type="button" class="btn btn-warning" onClick={() => editEmployee(item)} >Edit</button>)}
<button type="button" class="btn btn-dark" >Delete </button>
</td>
</tr>
</tbody>
);
})}
</table>
</div>
);
}
export default EmployeeLoad;
while Running the code this error displayed
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
There's no users.id and that's why the dynamically-constructed path is wrong and the API rejects it. http://127.0.0.1:8000/api/update/undefined
The error is thrown because of this line:
await axios.patch("http://127.0.0.1:8000/api/update/"+ users.id,
{
id: id,
name: name,
address: address,
mobile: mobile
});
You can try to await the call to the Load function in the useEffect.
Also, try adding if (!users) {return null;}
before the main JSX return.
I think there's something wrong with what your API returns.
Check what the users variable contains.
Something like:
import axios from 'axios';
import {useEffect, useState } from "react";
function EmployeeLoad()
{
const [id, setId] = useState('');
const [name, setName] = useState("");
const [address, setAddress] = useState("");
const [mobile, setMobile] = useState("");
const [users, setUsers] = useState([]);
useEffect(async ()=>
{
await Load();
},[])
async function Load()
{
const result = await axios.get(
"http://127.0.0.1:8000/api/employees");
setUsers(result.data);
console.log(result.data);
}
async function save(event)
{
event.preventDefault();
try
{
await axios.post("http://127.0.0.1:8000/api/save",
{
name: name,
address: address,
mobile: mobile
});
alert("Employee Registation Successfully");
setId("");
setName("");
setAddress("");
setMobile("");
}
catch(err)
{
alert("User Registation Failed");
}
}
async function editEmployee(users)
{
setName(users.name);
setAddress(users.address);
setMobile(users.mobile);
setId(users.id);
}
async function update(event)
{
event.preventDefault();
try
{
console.log('Let Aifos Si Prahs know what is here', users);
await axios.patch("http://127.0.0.1:8000/api/update/"+ users.find(u => u.id === id).id || id,
{
id: id,
name: name,
address: address,
mobile: mobile
});
alert("Employee Registation Successfully");
setId("");
setName("");
setAddress("");
setMobile("");
}
catch(err)
{
alert("User Registation Failed");
}
}
if (users.length <= 0) return null;
return (
<div>
<h1>Employee Details</h1>
<div class="container mt-4" >
<form>
<div class="form-group">
<input type="text" class="form-control" id="employee_id"
value={id}
onChange={(event) =>
{
setId(event.target.value);
}}
/>
<label>employeeName</label>
<input type="text" class="form-control" id="employeeName"
value={name}
onChange={(event) =>
{
setName(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>employeeAddress</label>
<input type="text" class="form-control" id="employeeAddress"
value={address}
onChange={(event) =>
{
setAddress(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>Mobile</label>
<input type="text" class="form-control" id="employeeMobile"
value={mobile}
onChange={(event) =>
{
setMobile(event.target.value);
}}
/>
</div>
<div>
<button class="btn btn-primary mt-4" onClick={save}>Register</button>
<button class="btn btn-primary mt-4" onClick={update}>Update</button>
</div>
</form>
</div>
<table class="table table-dark" align="center">
<thead>
<tr>
<th scope="col">Employee Id</th>
<th scope="col">Employee Name</th>
<th scope="col">Employee Address</th>
<th scope="col">Employee Mobile</th>
<th scope="col">Option</th>
</tr>
</thead>
{users.map(function fn(item)
{
return(
<tbody>
<tr>
<th scope="row">{item.id} </th>
<td>{item.name}</td>
<td>{item.address}</td>
<td>{item.mobile}</td>
<td>
<button type="button" class="btn btn-warning" onClick={() => editEmployee(item)} >Edit</button>)}
<button type="button" class="btn btn-dark" >Delete </button>
</td>
</tr>
</tbody>
);
})}
</table>
</div>
);
}
export default EmployeeLoad;
Althoug this won't help if your users object doesn't contain an id.
Related
I am beginner of react. I want to add and edit both operations at one button.
but it is not working. what i tried so far is the attached code along with the screenshot image.
I will able to add the records and able to view the records when i click the table row particular row record will be passing to form successfully. But I want edit and add the record of same button. i create the method save inside method I called save and edit functions
screenshot
this is the function i wrote the below
async function save(users)
import axios from 'axios';
import {useEffect, useState } from "react";
function EmployeeLoad()
{
const [name, setName] = useState("");
const [address, setAddress] = useState("");
const [mobile, setMobile] = useState("");
var currentEmployeeID = "";
const [users, setUsers] = useState([]);
useEffect(()=>
{
Load();
},[])
async function editEmployee(users)
{
setName(users.name);
setAddress(users.address);
setMobile(users.mobile);
currentEmployeeID = users.id;
console.log(users.id);
}
async function Load()
{
const result = await axios.get(
"http://127.0.0.1:8000/api/employees");
setUsers(result.data);
console.log(result.data);
}
async function save(users)
{
if(users.id == '')
{
await axios.post("http://127.0.0.1:8000/api/save",
{
name: name,
address: address,
mobile: mobile
}
);
alert("Employee Registation success");
}
else
{
alert("edit");
}
}
return (
<div>
<h1>Employee Details</h1>
<div class="container mt-4" >
<form>
<div class="form-group">
<label>employeeName</label>
<input type="text" class="form-control" id="employeeName"
value={name}
onChange={(event) =>
{
setName(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>employeeAddress</label>
<input type="text" class="form-control" id="employeeAddress"
value={address}
onChange={(event) =>
{
setAddress(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>Mobile</label>
<input type="text" class="form-control" id="employeeMobile"
value={mobile}
onChange={(event) =>
{
setMobile(event.target.value);
}}
/>
</div>
<button class="btn btn-primary mt-4" onClick={save}>Register</button>
</form>
</div>
<table class="table table-dark" align="center">
<thead>
<tr>
<th scope="col">Employee Id</th>
<th scope="col">Employee Name</th>
<th scope="col">Employee Address</th>
<th scope="col">Employee Mobile</th>
<th scope="col">Option</th>
</tr>
</thead>
{users.map(function fn(item)
{
return(
<tbody>
<tr>
<th scope="row">{item.id} </th>
<td>{item.name}</td>
<td>{item.address}</td>
<td>{item.mobile}</td>
<td>
<button type="button" class="btn btn-warning" onClick={() => editEmployee(item)} >Edit</button>
<button type="button" class="btn btn-dark" >Delete </button>
</td>
</tr>
</tbody>
);
})}
</table>
</div>
);
}
export default EmployeeLoad;
Inside your table use the currentEmployeeID and render a save button if you are in edit mode
{currentEmployeeID === item.id ? (
<button type="button" class="btn btn-warning" onClick={save} >Save</button> : (
<button type="button" class="btn btn-warning" onClick={() => editEmployee(item)} >Edit</button>
)}
So if this specific row is in edit mode, by pressing the button, it will save the entry, or else it will show "Edit". Dont forget to reset the currentEmployeeID when the save process completes.
I have a component called ListSuppliers, in it I have a bootstrap modal, it contains a table, and I want to populate that table from a postgresql table. Below is what I have in my Fragment section for the modal:
<div className="modal fade" id="myModal">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header d-flex justify-content-center">
<h4 className="modal-title">Supplier Name</h4>
</div>
<div className="modal-body">
<h3 className="text-center mt-2">Search Bar</h3>
<form>
<input
type="text"
className="form-control"
/>
</form>
<table className="table mt-5">
<thead>
<tr>
<th>Supplier Name</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{suppliers.map(supplier => (
<tr key={supplier.supplier_id}>
<td>{supplier.supplier_name}</td>
<td><button className="btn btn-danger" onClick={()=> deleteSupplier(supplier.supplier_id)}>Delete</button></td>
</tr>
))}
</tbody>
</table>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
And here is what I have for my ListSuppliers components and routes:
const ListSuppliers = () => {
const [suppliers, setSuppliers] = useState([]);
//Populate modal table function
const getSuppliers = async () => {
try {
const response = await fetch("http://localhost:5000/supplier");
const jsonData = await response.json();
setSuppliers(jsonData);
} catch (err) {
console.log(err.message);
}
}
//routes from index.js file
app.get("/supplier", async (req, res) => {
try {
const allSuppliers = await pool.query("SELECT supplier_name FROM supplier ORDER BY supplier_id ASC");
res.json(allSuppliers.rows);
} catch (err) {
console.error(err.message);
}
})
//Delete supplier entry
app.delete("/supplier/:id", async (req, res) => {
try {
const {id} = req.params;
const deleteSupplier = await pool.query('DELETE FROM supplier WHERE supplier_id = $1', [id]);
res.json(id);
} catch (err) {
console.error(err.message);
}
})
My modal displays the information as intended, however I'm getting this error:
Warning: Each child in a list should have a unique "key" prop
Check the render method of `ListSuppliers`
I don't understand why I'm getting the error as I included the key prop in table row:
{suppliers.map(supplier => (
<tr key={supplier.supplier_id}>
<td>{supplier.supplier_name}</td>
<td><button className="btn btn-danger" onClick={()=> deleteSupplier(supplier.supplier_id)}>Delete</button></td>
</tr>
))}
Any help is much appreciated
Check if supplier_id is present.
Lastly, try this and see if the warning comes up
{suppliers.map((supplier, index) => (
<tr key={index}>
<td>{supplier.supplier_name}</td>
<td><button className="btn btn-danger" onClick={()=> deleteSupplier(supplier.supplier_id)}>Delete</button></td>
</tr>
))}
I am new to react. I want to achieve the below functionality in react for a grading table of students. How can I do that?
Please refer to the images.
Change the table cell into an input box
Editable cells in the table
Here is the snippet I have tried till now
Improved your code. you can change as per your requirement. Live demo
const Grades = () => {
const [grade, setGrade] = useState("");
const [data, setData] = useState([]);
const [showEdit, setShoEdit] = useState(0);
var count = 0;
const handleChange = (event) => {
setGrade(event.target.value);
};
const addGrade = () => {
setData([...data, { Grade: grade, id: Math.floor(Math.random()*100) }]);
setGrade("");
};
const editGrade = (row) => {
console.log(row)
setShoEdit(row.id);
setGrade(row.id);
}
const saveGrade = (row) => {
let update = data.map(list =>
list.id === row.id ? ({...list, Grade: grade}) : list
);
setData([...update]);
}
return (
<div className="container-xl">
<div className="form-group row">
<div className="col-md-1">
<label className="col-form-label ">Grade</label>
</div>
<div className="col-md-4">
<input
type="text"
value={grade}
className="form-control"
name="Grade"
onChange={handleChange}
/>
</div>
{!showEdit && <div className="form-group col-md-6">
<button
type="button"
className="btn btn-outline-primary"
onClick={addGrade}
>
Add Grade
</button>
</div>}
</div>
<div className="form-group row">
<table className="table">
<thead className="thead-dark">
<tr>
<th>#</th>
<th>Grades</th>
<th>Grade Id</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
{data.map((row,i) => (
<tr key={row.id}>
<td>{++count}</td>
<td>{row.Grade}</td>
<td>{row.id}</td>
<td>
{!(row.id === showEdit) ? <button
onClick={()=> editGrade(row)}
key={row.id}
className="btn btn-outline-primary"
type="button"
>
Edit
</button>:
<button
type="button"
className="btn btn-outline-primary"
onClick={()=>saveGrade(row)}
>
Save
</button>}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default Grades;
I am trying to target a specific row to edit on my table in React.
My code looks something like this...
const [rowData, setRowData] = useState({ kind: { str: '', row: '' }});
const onChange = e => {
setRowData({...rowData, [e.target.name]: e.target.value }}
}
arr.map((ele, index) => (
<tr>
<td><input type='text' name='kind' value={kind.str} row={index} onChange={e => onChange(e)}></td>
</tr>
))
I didn't write all my code but I think that should be sufficient enough for an answer.
Basically I press a button edit that makes the row editable. When I press this button actually all rows and columns become editable which is not what I want but regardless of this outcome - I go to update the table and only that one input gets updated, unfortunately I get this error
A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component
After reading the error I then decided to change my onChange function to this...
const onChange = e => {
setRowData({...rowData, [e.target.name]: { str: e.target.value, row: e.target.getAttribute('row')}}
}
the above solves the issue from making my controlled component becoming uncontrolled however all the input fields on each row that match the kind name get updated which is not the desired functionality I want.
How can I solve this issue. Eventually what I want is an editable table that the user can update a single row and update the database with the data they input.
The arr variable I am using is actually named files.
I have another component which gets all my files from my database and sets it to the files variable
const [files, setFiles] = useState([]);
useEffect(() => {
const fetchFiles = async () => {
setLoading(true);
const res = await fetch('http://localhost:5000/api/files/all', {
method: 'GET',
});
const data = await res.json();
setFiles(data);
setLoading(false);
};
fetchFiles();
}, []);
I then pass in as props files to my Items component which is where the code that I wrote for my question lives in.
Most of the code is here...
ShowList component
const ShowList = () => {
const [files, setFiles] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [filesPerPage, setFilesPerPage] = useState(5);
const [yourUploads, setYourUploads] = useState(false);
useEffect(() => {
const fetchFiles = async () => {
setLoading(true);
const res = await fetch('http://localhost:5000/api/files/all', {
method: 'GET',
});
const data = await res.json();
setFiles(data);
setLoading(false);
};
fetchFiles();
}, []);
const indexOfLastPage = currentPage * filesPerPage;
const indexOfFirstPage = indexOfLastPage - filesPerPage;
const currentFiles = files.slice(indexOfFirstPage, indexOfLastPage);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
return (
<Fragment>
<div className='container'>
<h3 className='text-center'>
{yourUploads ? 'Your uploads' : 'All uploads'}
</h3>
<div className='d-flex dropdown'>
<button
className='btn mb-3 mr-3'
type='button'
id='dropdownMenuButton'
data-toggle='dropdown'
aria-haspopup='true'
aria-expanded='false'
>
Pages per row {filesPerPage}
</button>
<div className='dropdown-menu' aria-labelledby='dropdownMenuButton'>
<button
className='dropdown-item'
onClick={() => setFilesPerPage(5)}
>
5
</button>
<button
className='dropdown-item'
onClick={() => setFilesPerPage(10)}
>
10
</button>
</div>
<div className='dropdown'>
<button
className='btn mb-3'
type='button'
id='dropdownUploadsButton'
data-toggle='dropdown'
aria-haspopup='true'
aria-expanded='false'
>
{yourUploads ? 'your uploads' : 'all uploads'}
</button>
<div
className='dropdown-menu'
aria-labelledby='dropdownUploadButton'
>
<button
className='dropdown-item'
onClick={() => setYourUploads(true)}
>
your uploads
</button>
<button
className='dropdown-item'
onClick={() => setYourUploads(false)}
>
all uploads
</button>
</div>
</div>
</div>
<table id='myTable' className='table table-striped w-100'>
<thead>
<tr>
<th scope='col'>
<small>Title</small>
</th>
<th scope='col'>
<small>Kind</small>
</th>
<th scope='col'>
<small>Size</small>
</th>
<th scope='col'>
<small>Strength</small>
</th>
<th scope='col'>
<small>Combinations</small>
</th>
<th scope='col'>
<small>Favors</small>
</th>
<th scope='col'>
<small>Stock</small>
</th>
<th scope='col'>
<small>Carousel</small>
</th>
<th scope='col'>
<small>Owner</small>
</th>
<th scope='col'>
<small>Edit</small>
</th>
<th scope='col'>
<small>Delete</small>
</th>
</tr>
</thead>
<Items
files={currentFiles}
loading={loading}
yourUploads={yourUploads}
/>
</table>
<Pagination
filesPerPage={filesPerPage}
totalFiles={files.length}
paginate={paginate}
/>
</div>
</Fragment>
);
};
Items component
const Items = ({ files, loading, yourUploads }) => {
const [myUploads, setMyUploads] = useState([]);
const [editable, setEditable] = useState(false);
const [rowData, setRowData] = useState({
kind: { str: '', row: '' },
});
const { kind } = rowData;
useEffect(() => {
const fetchMyUploads = async () => {
const res = await fetch('http://localhost:5000/api/files/all/mine', {
method: 'GET',
});
const data = await res.json();
setMyUploads(data);
};
fetchMyUploads();
}, [files]);
const onChange = (e) => {
setRowData({ ...rowData, [e.target.name]: e.target.value });
};
const onSubmit = async (e, file_id) => {
e.preventDefault();
if (!editable) {
setEditable(!editable);
} else {
await fetch(`http://localhost:5000/api/files/${file_id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(rowData),
});
setEditable(!editable);
}
};
if (loading) {
return (
<tbody>
<tr>
<td>loading...</td>
</tr>
</tbody>
);
}
const list = yourUploads
? myUploads.map((file) => (
<tr key={file._id}>
<td>
<small>{file.title}</small>
</td>
<td>
<small>{file.kind}</small>
</td>
<td>
<small>{file.size}</small>
</td>
<td>
<small>{file.strength}</small>
</td>
<td>
<small>{file.combinations}</small>
</td>
<td>
<small>{file.favors}</small>
</td>
<td>
<small
className={file.availability ? 'alert-success' : 'alert-danger'}
>
{file.availability ? 'in stock' : 'out of stock'}
</small>
</td>
<td>
<small>{file.isCarousel ? 'carousel' : 'not caorousel'}</small>
</td>
<td>
<small>{file.owner}</small>
</td>
<td>
<button className='btn btn-dark'>
<small>edit</small>
</button>
</td>
<td>
<button className='btn btn-danger'>
<small>delete</small>
</button>
</td>
</tr>
))
: files.map((file, index) => (
<tr key={file._id}>
<td>
<small>{file.title}</small>
</td>
<td>
<small>
{editable ? (
<input
type='text'
name='kind'
value={kind.str}
row={index}
onChange={(e) => onChange(e)}
/>
) : (
file.kind
)}
</small>
</td>
<td>
<small>{file.size}</small>
</td>
<td>
<small>{file.strength}</small>
</td>
<td>
<small>{file.combinations}</small>
</td>
<td>
<small>{file.favors}</small>
</td>
<td>
<small
className={file.availability ? 'alert-success' : 'alert-danger'}
>
{file.availability ? 'in stock' : 'out of stock'}
</small>
</td>
<td>
<small>{file.isCarousel ? 'carousel' : 'not carousel'}</small>
</td>
<td>
<small>{file.owner}</small>
</td>
<td>
<button
className='btn btn-dark'
onClick={(e) => onSubmit(e, file._id)}
>
<small>{editable ? 'save' : 'edit'}</small>
</button>
</td>
<td>
<button className='btn btn-danger'>
<small>delete</small>
</button>
</td>
</tr>
));
return <tbody>{list}</tbody>;
};
This error message usually comes up when you pass null or undefined to the input value prop. If value prop is empty, then react thinks it became uncontrolled component.
So you need to fix the error here.
arr.map((ele, index) => (
<tr>
<td><input type='text' name='kind' value={kind.str} row={index} onChange={e => onChange(e)}></td>
</tr>
))
Change value={kind.str} to value={rowData.kind.str}
Thanks everyone for answering my question. I was able to figure it out by splitting my components. So from my Items I render an Item component that renders the item and an Edit component that brings props in for that row only. By doing this I was able to eliminate the need for a row field which therefore gets rid of my error. React knows which row I am editing.
I am attempting to execute a function through an onclick event, however, nothing happens. My aim is to have the function firing off once the download button in the pop-up window is clicked. My aim is to have the downloadJobs event fire once the Download button is clicked.
Any advice to resolve this issue would be truly appreciated.
class LoadTable extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
Search: "Search",
visible: false,
sort: {
column: null,
direction: 'desc',
},
}
this.doSearch = this.doSearch.bind(this);
this.runLog = this.runLog.bind(this);
this.downloadOutput = this.downloadOutput.bind(this);
}
componentDidMount() {
this.props.getJobs()
.then((res) => {
this.setState({
data: res.results.response || [],
visible: false
})
});
}
doSearch(e) {
const { name, value } = e.target;
this.setState({
[name]: value
});
console.log("Initiate Search");
}
runLog() {
console.log("Initiate Run Log");
}
downloadOutput() {
var name = document.getElementById('logBody');
console.log("execute");
//const element = document.createElement("a");
//const file = new Blob([content], { type: 'text/plain' });
//element.href = URL.createObjectURL(file);
//element.download = "log.txt";
//document.body.appendChild(element); // Required for this to work in FireFox
//element.click();
}
render() {
const { data, Search, visible } = this.state;
return data.length > 0 ? (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
<div id="Search" className="row col-xs-5 col-lg-2">
<div className="form-group">
<input className='form-control' type="text" placeholder="Search" name="Search" value={Search} onChange={this.doSearch} autoFocus />
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<th onClick={e => this.doSort('name')}>Name</th>
<th onClick={e => this.doSort('job')}>Job</th>
<th onClick={e => this.doSort('start')}>Start</th>
<th onClick={e => this.doSort('end')}>End</th>
<th onClick={e => this.doSort('status')}>Status</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{
data.map((dt) => {
return (
<tr key={dt.id}>
<td>{dt.name}</td>
<td>{dt.job}</td>
<td>{dt.start}</td>
<td>{dt.end}</td>
{ dt.status ?
<td>
<div className="alert alert-success" role="alert"></div>
</td>
:
<td>
<div className="alert alert-danger" role="alert"></div>
</td>
}
<td><button type="button" className="btn btn-primary" onClick={this.runLog}>Run Job</button></td>
<td><button type="button" className="btn btn-info" onClick={() => this.refs.modalLog.open()}>View Run Log</button>
<PureModal
header={dt.name}
scrollable
width="300px"
draggable
footer={<div><button type="button" className="btn btn-info" onClick={() => this.downloadOutput }>Download Job {dt.name}</button></div>}
onClose={this.HandleClose}
ref="modalLog"
>
<p id="logBody">{dt.logs}</p>
</PureModal>
</td>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
) :
<div className="row">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>No Data to Display at the moment</p>
</div>
</div>;
}
}
function mapStateToProps(state) {
return {
};
}
const mapDispatchToProps = dispatch => ({
getJobs: () => dispatch(jobActions.getJobs())
});
export default connect(mapStateToProps, mapDispatchToProps)(LoadTable);
The way this onClick handler is set up right now is that it is invoking a call back function which returns you the downloadOutput function but this function itself is not being invoked since no () are present. You would need to rewrite it to be onClick={() => this.downloadOutput()}
However, since downloadOuput is not receiving any parameters, you don't have to have it invoke through a call back function, then the onClick event itself will be used to invoke this function directly. onClick={this.downloadOutput}
Also,
this.downloadOutput = this.downloadOutput.bind(this) within the constructor to bind the this value.
Hope that helped (: