Display no results when table empty in React - arrays

I have a table of rows that display contact information. I'd like to have it render a messasge of "No contacts" when the listItems array is 0. I tried creating a const noEntries variable and setting it with the array to 0, and using {noEntries No entries}, but this is throwing an error.
class ContactList extends Component {
constructor(props) {
super(props);
this.createContact = this.createContact.bind(this);
}
delete(key) {
this.props.delete(key);
}
createContact(item) {
return <tr key={item.key}>
<td>{item.firstname}</td>
<td>{item.lastname}</td>
<td>{item.phone}</td>
<td><i className="fas fa-trash-alt" onClick={() => { if (window.confirm('Are you sure you want to delete ' + item.firstname + ' ' + item.lastname + ' from your contacts?')) this.delete(item.key)}}></i></td>
</tr>
}
render() {
const contactEntries = this.props.entries;
const listItems = contactEntries.map(this.createContact);
return (
<table className="mui-table mui-table--bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</table>
);
}
};
export default ContactList;

in your render() do like this:
render() {
const contactEntries = this.props.entries;
const listItems = contactEntries.map(this.createContact);
return (
contactEntries.length > 0?
<table className="mui-table mui-table--bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</table>:<span>No results</span>
);
}

check the number of records in contactEntries using ternary operator if length ==0 then return no data component else return rows
const listItems = contactEntries && contactEntries.length >0
? contactEntries.map(this.createContact)
: <tr key={item.key}>
<td rowspan="3">No data</td
</tr>

Related

How to get rowIndex in Reactjs?

I have a table using normal HTML in reactjs:
const [user, setUser] = useState(null);
useEffect(() => {
axios
.get("http://localhost:8080/api/users")
.then((response) => {
setUser(response.data);
});
}, [url]);
const [rowIndex, setRowIndex] = useState("");
if (user) {
return (
<div>
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Department</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{user.map((item) => (
<tr>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.department}</td>
<td><button>Click</button></td>
</tr>
))}
</tbody>
</table>
</div>
);
}
If in Javascript, I can simply set <tr onclick="getIndex(this)"> and calling function getIndex(x) {console.log(x.rowIndex)} to get the row number.
But it's not working in ReactJS. How can I get the rowIndex in ReactJS?
Use index inside your map method and then use this variable inside your button's onClick method
const [user, setUser] = useState(null);
useEffect(() => {
axios
.get("http://localhost:8080/api/users")
.then((response) => {
setUser(response.data);
});
}, [url]);
const [rowIndex, setRowIndex] = useState("");
if (user) {
return (
<div>
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Department</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{user.map((item, index) => (
<tr>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.department}</td>
<td><button onclick={() => setRowIndex(index)}>Click</button></td>
</tr>
))}
</tbody>
</table>
</div>
);
}

Data not Rendering in HTML but in log it shows

Rendering not working in td tag, outside td the data is showing but not getting rendering HTML.
td not working.
Data is printing if do console.log but not getting render in HTML
SetArrayTime((prev_array_time) => {
let newArray = [...prev_array_time];
newArray.push(intervals);
return newArray;
});
};
return (
<table className="table table-bordered">
<thead className="thead text-center">
<tr>
<th scope="col">From</th>
<th scope="col">To</th>
</tr>
</thead>
<tbody>
{array_time &&
array_time.map((d, i) => {
console.log("123-d", d);
return (
<tr key={i}>
<td>
{d.from}-{d.to}
</td>
<td></td>
</tr>
);
})}
</tbody>
</table>
);
map return array of react elemnt,react by default map of the array and render. it does not need return
Try this
{array_time?.map((d, i) => (
<tr key={i}>
<td>
{d.from}-{d.to}
</td>
<td></td>
</tr>
))}

how to output axios returned data to screen

I am successfully returning data from my axios call on page load.
constructor(props) {
super(props);
this.state = {
myData: []
}
}
componentDidMount() {
let context= this;
axios.get('http://localhost:3000/returntestvalues',{
})
.then((res) => {
console.log("Res os: ", res.data)
context.setState({
myData: res.data
});
})
console.log("res.data", this.state.myData)
}
As you can see there, I am setting the State to the returned data. Now, I want to output this into a table:
render() {
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
<tr>
{this.state.myData?.length > 0
? this.state.myData.map((data, index) => (
<tr key={index}>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</tr>
))
: "No Data Found"}
</tr>
</table>
</body>
);
}
}
however, I don't know how to do this through react, I've only ever done it through ejs. Can anyone help?
render() {
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
<tr>
{this.state.myData?.length > 0
? this.state.myData.map((data, index) => (
<React.Fragment key={index}>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</React.Fragment>
))
: "No Data Found"}
</tr>
</table>
</body>
);
}
}
Here i am assuming that the keys are name email and message. you can change yours.
You can map your received data like below.
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
{this.state.myData?.length>0 && this.state.myData.map(function(data,index){
return (<tr>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</tr>);
})}
</table>
</body>
);

React typescript, how to find all words between '#' in the string

I've got a question about some solution for my problem.. I need to find all words between '#' in the string...
example:
const str = `<Table striped bordered hover>
<thead>
<tr>
<th>#project name#</th>
<th>#First Name#</th>
<th>#Last Name#</th>
<th>#Username#</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<td>3</td>
<td colSpan="2">#Footer#</td>
<td>#social media#</td>
</tr>
</tbody>
</Table>
<p> normal text: #Published data# </p>
`
is there any method? I have to find in my table that I could to replace those words for words from database. I thought about proptype.replaceAll, but I couldn't solve it by this :/
String.prototype.replaceAll() should work. Perhaps you weren't using it correctly? We want to use a RegExp that lazily matches the text between two # symbols with a capture group. Then you can use whatever callback function to replace the values.
The Typescript is a little weird because TS doesn't know that our RegExp has a capture group and that we will always get a string as the second argument of the replacer function. It is typed such that the second argument, which is our capture group, could be any type.
/**
* this is where you implement your actual replacement logic
*/
const findReplacement = (text: string) => {
switch (text.toLowerCase()) {
case 'project name':
return '<span class="project">Project</span>';
case 'footer':
return "Replacement for Footer";
default:
return text;
}
}
/**
* function to handle a string like your example
*/
const processTemplate = (text: string) => {
return text.replaceAll(
/#(.*?)#/g,
(_, match) => findReplacement(match)
);
}
Try it on your string with
console.log(processTemplate(str));
Typescript Playground Link
Runnable Stack Snippet (no TS)
const findReplacement = (text) => {
switch (text.toLowerCase()) {
case 'project name':
return '<span class="project">Project</span>';
case 'footer':
return "Replacement for Footer";
default:
return text;
}
}
const processTemplate = (text) => {
return text.replaceAll(
/#(.*?)#/g,
(_, match) => findReplacement(match)
);
}
const str = `<Table striped bordered hover>
<thead>
<tr>
<th>#project name#</th>
<th>#First Name#</th>
<th>#Last Name#</th>
<th>#Username#</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<td>3</td>
<td colSpan="2">#Footer#</td>
<td>#social media#</td>
</tr>
</tbody>
</Table>
<p> normal text: #Published data# </p>`;
console.log(processTemplate(str));
const str = `<Table striped bordered hover>
<thead>
<tr>
<th>#project name#</th>
<th>#First Name#</th>
<th>#Last Name#</th>
<th>#Username#</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<td>3</td>
<td colSpan="2">#Footer#</td>
<td>#social media#</td>
</tr>
</tbody>
</Table>
<p> normal text: #Published data# </p>`;
const words = [];
let start = false;
let word = "";
for (let i = 0; i < str.length; i++) {
if (str[i] === "#") {
if (start) words.push(word);
word = "";
start = !start;
} else {
if (start) {
word += str[i];
}
}
}
console.log(words);

Adjacent Jsx elements must be wrapped in an e

i have a very annoying error when trying to display stuff in react table , i would like to make a table and display all values in rows , but for some reason i am getting this error saying Adjacent jsx elemetns must be wrapped in an enclosing element next to the line where im trying to map over results. Any help is greatly appreciated !! thanks!!!
import React from "react";
import "./index.css";
// could also import the sass if you have a loader at dayz/dayz.scss
import moment from 'moment';
import { tasksRef, timeRef } from './firebase';
const defaultColor = "#000";
class Show extends React.Component {
state = {
Events: [],
loading: true
};
render(){
const { Events, Loading } = this.state;
const orderedcars = Events;
let List;
if (Loading) {
List = <div className="TaskList-empty">Loading...</div>;
} else {
List = (
<div>
<table>
<thead>
<tr>
<th scope="row">Event Name</th>
<th scope="row">Event date</th>
<th scope="row">Event timeRef</th>
</tr>
</thead>
<tbody>
{Events.map(car => (
<tr>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
</tbody>
</table>
))}
</div>
);
}
return(
<div>
{List}
</div>
);
}
}
export default Show;
the problem is that the closing tbody and table atgs should be outside map function as follows
{Events.map(car => (
<tr key={car.name}>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
))}
You want to place the closing </tbody> and </table> tags outside of the function given to Events.map.
List = (
<div>
<table>
<thead>
<tr>
<th scope="row">Event Name</th>
<th scope="row">Event date</th>
<th scope="row">Event timeRef</th>
</tr>
</thead>
<tbody>
{Events.map(car => (
<tr>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
))}
</tbody>
</table>
</div>
);

Resources