I could render the herader's table users through for exemple: {user[name]}. But I couldn't render the header itself who is the [name] for example rendering: name of Leanne Graham. Can anyone help me with this?
import React from 'react'
const Users= ({ users}) => {
return (
<div>
{users.map((user,index) => (
<div key={index}>
<div className="container smcontainer d-flex justify-content-start">
<div className="row">
<div className="col-md-12">
<table className="table table-striped">
<thead>
</thead>
<tbody>
<tr>
<td className=""> {user['id']} </td>
<td className=""> {user['name']} </td>
<td className=""> {user['username']} </td>
<td className=""> {user['email']} </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
))}
</div>
)}
export default Products
This is the App component
class App extends Component {
constructor(props){
super(props)
this.state= {
users: [],
}
}
async componentDidMount() {
const url = ('https://jsonplaceholder.typicode.com/users')
const response = await fetch (url)
const data = await response.json()
this.setState({users: data.itemsList})
console.log({users: data.itemsList})
}
render() {
return (
<Users users = {this.state.users} />
)
}
}
export default App;
When you map over an array, whatever you return is returned each time for every element in the array. This code will create a whole new table for each user.
I think what you want to do is define your column headers separately from your map call and then map over the array to generate the rows:
const columns = ["ID", "Name", "Username", "Email"];
...
<div>
<div className="container smcontainer d-flex justify-content-start">
<div className="row">
<div className="col-md-12">
<table className="table table-striped">
<thead>
{columns.map(c => <th>{c}</th>)}
</thead>
<tbody>
{users.map((user, index) => (
<tr>
<td className=""> {user['id']} </td>
<td className=""> {user['name']} </td>
<td className=""> {user['username']} </td>
<td className=""> {user['email']} </td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
I made a Codepen demonstrating both ways, but to me the first one makes much more sense.
That should give you what you want.
<thead>
{user['name']}
<thead/>
If you want to take the first name of Leanne Graham, you can do:
<thead>
{user['name'].split(" ")[0]}
<thead/>
Related
I am not a react expert, and I am trying to integrate a gridjs component with react-beautiful-dnd library. The objective is to add drag and drop functionaly to a gridjs table.
I have create a react component, that looks like this:
import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
function ForwardGrid({userdata}, ref) {
const users = userdata.data;
return (<>
<div ref={ref}>
<DragDropContext>
<table>
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Age</th>
<th>Gender</th>
</tr>
</thead>
<Droppable droppableId="droppable-1">
{(provider) => (
<tbody
className="text-capitalize"
ref={provider.innerRef}
{...provider.droppableProps}
>
{users?.map((user, index) => (
<Draggable
key={user.name}
draggableId={user.name}
index={index}
>
{(provider) => (
<tr {...provider.draggableProps} ref={provider.innerRef}>
<td {...provider.dragHandleProps}> =</td>
<td>{user.name}</td>
<td>{user.age}</td>
<td>{user.gender}</td>
</tr>
)}
</Draggable>
))}
{/*{provider.placeholder}*/}
</tbody>
)}
</Droppable>
</table>
</DragDropContext>
</div>
</>)
}
const forwardTable = React.forwardRef(ForwardGrid);
export default forwardTable;
this component return a forwardref, which is used in a parent component.
const tableRef = useRef(null);
const wrapperRef = useRef(null);
const [users, setUsers] = useState(userdata.data);
useEffect(() => {
console.log(tableRef.current)
const grid = new Grid({
from: tableRef.current,
}).render(wrapperRef.current);
}, []);
return (
<>
<div className="App mt-4">
<ForwardGrid ref={tableRef} userdata={userdata}/>
<div ref={wrapperRef}/>
</div>
</>
);
However, once .render(wrapperRef.current) is fired, the table is rendered but the drag and drop doesn't work. I have inspected the html generated and I have noticed that it is not correct. It does not contain all the attributes that react-beautiful-dnd would generate normally (for instance data-rbd-draggable-id, data-rbd-draggable-context-id etc).The drag and drop functionalty works fine with a normal html table.
I would expect this html generated.
<tr data-rbd-draggable-context-id="0" data-rbd-draggable-id="Subham" style="">
<td tabindex="0" role="button" aria-describedby="rbd-hidden-text-0-hidden-text-0"
data-rbd-drag-handle-draggable-id="Subham" data-rbd-drag-handle-context-id="0" draggable="false"> =
</td>
<td>Subham</td>
<td>21</td>
<td>male</td>
</tr>
insted it returns this.
<tr class="gridjs-tr">
<td data-column-id="#" class="gridjs-td">=</td>
<td data-column-id="username" class="gridjs-td">Jeevan</td>
<td data-column-id="age" class="gridjs-td">21</td>
<td data-column-id="gender" class="gridjs-td">male</td>
</tr>
any idea how can I solve the problem?
I am trying to use the data store in mongodb collection and render it in the front end. It renders the text box, labels and search button, even though it does not load any of the data. My collection name is users and my database CRDU works perfectly fine.
Please help me with this, below is my front end search.js
function Search(){
const [resultUsers, setResultUsers] = useState([]);
const [usersTable, setUsersTable] = useState([]);
const [searchP, setSearchP] = useState("");
const requestGet=async()=>{
await axios.get("mongodb://localhost:27017/projectDB/users/")
.then(response=>{
setResultUsers(response.data);
setUsersTable(response.data);
}).catch(error=>{
console.log(error);
})
}
const handleChange=e=>{
setSearchP(e.target.value);
filter(e.target.value);
}
const filter=(searchTerm)=>{
var searchResults=usersTable.filter((element)=>{
if(element.username.toString().toLowerCase().includes(searchTerm.toLowerCase())
|| element.firstName.toString().toLowerCase().includes(searchTerm.toLowerCase())
|| element.lastName.toString().toLowerCase().includes(searchTerm.toLowerCase())
){
return element;
}
});
setResultUsers(searchResults);
}
useEffect(()=>{
requestGet();
},[])
return (
<div className="Search">
{/* <Container> */}
<div className="containerInput">
<input
className="form-control search-input"
value={searchP}
placeholder="Enter username, first name or last name of the user to begin search"
onChange={handleChange} />
<button className="btn btn-success">Search for users
</button>
<br/>
</div>
{/* </Container> */}
<div className='tabled'>
<div className="table-responsive">
{/* <Container> */}
<table className="table table-sm table-bordered;">
<thead>
<tr>
<th>Username</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
{resultUsers &&
resultUsers.map((resultUsers)=>(
<tr key={resultUsers.id}>
<td>{resultUsers.username}</td>
<td>{resultUsers.firstName}</td>
<td>{resultUsers.lastName}</td>
</tr>
))}
</tbody>
</table>
{/* </Container> */}
</div>
</div>
</div>
)
}
export default Search
Thanks in advance!!
I have a dynamic Accordion in ReactJs. I am getting the message from my backend. but it's printing in every Accordion. I'm sharing the code
import React, { useState, useEffect } from "react";
import ApplicantDash from "./ApplicantDash";
import {
Accordion,
AccordionSummary,
AccordionDetails,
Typography,
} from "#material-ui/core";
import * as FcIcons from "react-icons/fc";
import ApplicantService from "../services/ApplicantService";
export default function AvailJobs() {
const [aplcntEmail, setAplcntEmail] = useState("aman#gmail.com"); //change to aplcntemail
const [isShow, setIsShow] = useState(false);
const [msg, setMsg] = useState([""]);
const [job, setJob] = useState([
{
jobTitle: "",
dateOfPosting: Date,
lastDateToApply: new Date().toLocaleDateString([], {
year: "numeric",
month: "long",
day: "numeric",
}),
preferableSkills: [],
requiredExp: 0,
recruiterEmail: "",
companyName: "",
companyAddress: "",
},
]);
useEffect(() => {
const data = ApplicantService.getAllJobs()
.then((response) => {
console.log(response.data);
setJob(response.data);
})
.catch((error) => {
alert(error.response.data);
});
}, []);
const onApplyButton = (item,key) => {
const data2 = ApplicantService.applyForJob(aplcntEmail, item)
.then((response) => {
console.log(response.data);
setIsShow(true);
setMsg(response.data)
})
.catch((error) => {
setIsShow(true);
setMsg(error.response.data);
});
};
return (
<div>
<ApplicantDash />
<div className="container bg-light">
<div className="card-bodies">
<section className="mb-4">
<h2 className="h1-responsive font-weight-bold text-center my-4">
All Available jobs
</h2>
</section>
{job.map((item, key) => (
<>
<Accordion key={key}>
<AccordionSummary
expandIcon={<FcIcons.FcExpand />}
aria-controls="panel1a-content"
id="panel1a-header"
className="Accordian"
>
<Typography>
<div className="d-flex p-1 justify-content-evenly">
<div className="p-1">
<b> Job: </b> {item.jobTitle}
</div>
<div className="p-2"></div>
<div className="p-1">
<b> Company: </b> {item.companyName}
</div>
<div className="p-2"></div>
<div className="p-1">
<b> Last Date: </b> {item.lastDateToApply}
</div>
</div>
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
<div className="container">
<table class="table table-borderless">
<tbody>
<tr>
<td>JOB TITLE</td>
<td>:</td>
<td>
<b>{item.jobTitle}</b>
</td>
</tr>
<tr>
<td>Company</td>
<td>:</td>
<td>
<b>{item.companyName}</b>
</td>
</tr>
<tr>
<td>Address</td>
<td>:</td>
<td>
<b>{item.companyAddress}</b>
</td>
</tr>
<tr>
<td>Last Date to Apply</td>
<td>:</td>
<td>
<b>{item.lastDateToApply}</b>
</td>
</tr>
<tr>
<td>Experience</td>
<td>:</td>
<td>
<b>{item.requiredExp}</b>
</td>
</tr>
<tr>
<td> Skills </td>
<td>:</td>
<td>
<table className="table table-condensed w-auto table-borderless table-hover">
{item.preferableSkills.map((S, index1) => {
return (
<tbody key={index1}>
<td scope="col">
{index1 + 1}.<b>{S}</b>
</td>
</tbody>
);
})}
</table>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
<button
type="button"
class="btn btn-primary"
onClick={() => onApplyButton(item,key)}
>
Apply for the job{" "}
</button>
</td>
</tr>
</tbody>
{isShow && <>
{msg}
</>}
</table>
</div>
</Typography>
</AccordionDetails>
</Accordion>
</>
))}
</div>
</div>
</div>
);
}
Now when I click on Apply for this job button. The message I get from backend prints only to Active accordion
Here some pictures which might help.
enter image description here
As you can see the response from backend is prints in the both of the accordion
Issue
The issue here is that you've a single boolean isShow state and a single msg state, and all the accordion detail sections use the same single isShow state to conditionally render the msg state.
Solution
A simple solution would be to store the id, or title, or index, of the accordion to show the message of.
Example:
export default function AvailJobs() {
...
const [isShow, setIsShow] = useState({}); // <-- initially empty object
...
const onApplyButton = (item, key) => {
ApplicantService.applyForJob(aplcntEmail, item)
.then((response) => {
console.log(response.data);
setMsg(response.data);
})
.catch((error) => {
setMsg(error.response.data);
})
.finally(() => {
setIsShow(show => ({
...show,
[key]: true // <-- set true the specific key
}));
});
};
return (
<div>
...
{job.map((item, key) => (
<Accordion key={key}>
...
<AccordionDetails>
<Typography>
<div className="container">
<table class="table table-borderless">
<tbody>
...
<tr>
...
<td>
<button
type="button"
class="btn btn-primary"
onClick={() => onApplyButton(item, key)}
>
Apply for the job
</button>
</td>
</tr>
</tbody>
{isShow[key] && <>{msg}</>} // <-- check if isShow[key] is truthy
</table>
</div>
</Typography>
</AccordionDetails>
</Accordion>
))}
...
</div>
);
}
I am trying to create a dropdown/collapse area within a table row that is the full width of the table with Bootstrap 4 and React JS. I haven't been able to find a visual of what I want, I just remember using it somewhere before (maybe on AWS?), but I haven't been able to locate it again.
EDIT: Desired action has been found (https://i.imgur.com/Pcg1JgI.png). Once the chevron is clicked, the below rows open.
This is my current code:
import React from "react";
import { API, graphqlOperation } from 'aws-amplify';
import { listTrackerItems } from '../graphql/queries';
class TrackerGeneralPage extends React.Component {
state = {
id: '',
active: [],
completed: [],
completedDateNow: '',
newStatus: 'Complete'
};
async componentDidMount() {
const result = await API.graphql(graphqlOperation(listTrackerItems))
let data = result.data.listTrackerItems.items
let General = data.filter(t=>t.department === 'General');
const activeGeneral = General.filter(t=>t.status === 'Active');
const completedGeneral = General.filter(t=>t.status === 'Completed');
const date = new Date();
const month = date.getUTCMonth() + 1;
const day = date.getUTCDate();
const year = date.getUTCFullYear();
const timeNow = month + "/" + day + "/" + year;
this.setState({active: activeGeneral, completed: completedGeneral, completedDateNow: timeNow });
}
render() {
const { active } = this.state
return (
<>
<div>
<div class="container">
<div class="row">
<div class="col-sm">
</div>
<div class="col-sm">
<div className="mx-auto" align="center">
<h1>General</h1>
</div>
</div>
<div class="col-sm">
<div className="mx-auto mt-2" align="center">
{/* <!-- Button trigger modal --> */}
<a role="button" className="btn btn-dark" href="/tracker/nwa/lab/add" >
Add Tracker
</a>
</div>
</div>
</div>
</div>
{/* Active Trackers */}
<div id="toggle-active" className="">
<div className="my-4">
<table className="table table-hover table-bordered mb-3">
<thead className="thead-dark">
<tr>
<th scope="col">Actions</th>
<th scope="col">Name</th>
<th scope="col">Regulation</th>
{/* <th scope="col">Occurrence</th> */}
<th scope="col">Due On</th>
<th scope="col">Assigned</th>
<th scope="col">Status</th>
{/* <th scope="col">Completer</th>
<th scope="col">Date Completed</th>
<th scope="col">Description</th> */}
</tr>
</thead>
<tbody>
{active.map(item => (
<tr key={item.id}>
<th scope="row" className="dropdown">
<a class="btn" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample"><img src="https://icon.now.sh/chevronDown" width="25" height="25" className="d-inline-block align-top" alt="Open Row" /></a>
</th>
<td>{item.name}</td>
<td>{item.reg}</td>
<td>{item.dateDue}</td>
<td>{item.assigned}</td>
<td>{item.status}</td>
<div class="collapse" id="collapseExample">
<div class="card card-body">
<td>{item.occurrence}</td>
<td>{item.completer}</td> */}
<td>{item.dateCompleted}</td>
<td>{item.description}</td>
</div>
</div>
</tr>
))}
</tbody>
</table>
</div> {/* End Table Section */}
</div> {/* End Active Toggle */}
</div> {/* End Container */}
</>
)
}
}
export default TrackerGeneralPage;
If I currently click the dropdown arrow, it places it to the right side of the table: visual on imgur.
If I move this:
<div class="collapse" id="collapseExample">
<div class="card card-body">
<td>{item.occurrence}</td>
<td>{item.completer}</td> */}
<td>{item.dateCompleted}</td>
<td>{item.description}</td>
</div>
</div>
into the <th> where the dropdown/collapse button is located, it places it all into that specific column only: visual on imgur.
I would like the button to open the dropdown/collapse area directly under the table row, as if its attached, (pushing the row beneath further down) and be full width of the table/row.
Each button would need to only open that specific rows dropdown/collapse area as well, and right now if I click any button, it opens all of the rows dropdown/collapse areas.
How is this accomplished/what is this called?
Take this as an idea. Simply add collapse to your <td> and overwrite bootstrap <td> padding;
You can pass value to replace the data-target with unique id for each row like fd1, fd2or other id name that can avoid collision via your map function.
/*overwrite bootstrap table padding*/
.hiddenRow {
padding: 0 !important;
}
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<table class="table table-hover">
<thead>
<th></th><th>1</th><th>2</th><th>3</th>
</thead>
<tbody>
<tr data-toggle="collapse" data-target="#folder1">
<td class="text-center"><span>+</span></td>
<td>Cell 1.1</td>
<td>Cell 1.2</td>
<td>Cell 1.3</td>
</tr>
<tr>
<td colspan="4" class="hiddenRow">
<div id='folder1' class="collapse">
row1
</div>
</td>
</tr>
<tr data-toggle="collapse" data-target="#folder2">
<td class="text-center"><span>+</span></td>
<td>Cell 2.1</td>
<td>Cell 2.2</td>
<td>Cell 2.3</td>
</tr>
<tr style="background:lightyellow">
<td colspan="4" class="hiddenRow">
<div id="folder2" class="collapse">
row2
</div>
</td>
</tr>
</tbody>
</table>
I am tryng to display search results for each key press on my input:
getMovies(e){
axios.get(`http://www.omdbapi.com/?t=${e.target.value}`)
.then((response) => {
this.setState({ movies: response.data });
})
.catch((error) => {
console.log(error);
});
}
render() {
return (
<div className="container">
<SearchForm onkeydown={this.getMovies} />
<MovieList movies={this.state.movies}/>
</div>
);
}
}
In my search form I bind my function to the FormControl onChange:
export default class SearchForm extends React.Component{
render(){
return(
<Row>
<Col md={6} >
<h2>Custom search field</h2>
<div className="custom-search-input">
<Col md={12} className="input-group" >
<FormControl
type="text"
bsSize="lg"
value={this.props.val}
placeholder="Enter text"
onChange={this.props.onkeydown.bind(this)}
/>
<span className="input-group-btn">
<button className="btn btn-lg" type="button">
<i className="glyphicon glyphicon-search"></i>
</button>
</span>
</Col>
</div>
</Col>
</Row>)
}
}
My movielist component:
export default class MovieList extends React.Component{
render(){
var userNodes = this.props.movies.map(function(movie){
return (
<tr key={movie.id}>
<td>{movie.Year}</td>
<td >{movie.Title}</td>
<td >{movie.Released}</td>
</tr>
)
});
return (
<div>
<Table responsive>
<thead>
<tr>
<th>id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
{userNodes}
</tbody>
</Table>
</div>
);
}
}
I can get the response on the network panel, but the state is not updating to display the MovieList component.
How can I update the state and display it in my MovieList ?
I've checked that API and seems it returns an object, not an array.
Update 1
You can convert your component in something like:
export default class MovieList extends React.Component{
render(){
const { movie } = this.props;
return (
<div>
<Table responsive>
<thead>
<tr>
<th>Id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
<tr>
<td>{movie.imdbID}</td>
<td>{movie.Year}</td>
<td>{movie.Title}</td>
<td>{movie.Released}</td>
</tr>
</tbody>
</Table>
</div>
);
}
}
and use it like:
<MovieList movie={this.state.movies} />
Please notice I'm using movie instead of movies.
Update 2:
You can also (and I would suggest doing this) convert your MovieList into a dumb functional component:
const MovieList = ({ movie }) => (
<div>
<Table responsive>
<thead>
<tr>
<th>Id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
<tr>
<td>{movie.imdbID}</td>
<td>{movie.Year}</td>
<td>{movie.Title}</td>
<td>{movie.Released}</td>
</tr>
</tbody>
</Table>
</div>
)
export default MovieList;