I'm having problems showing/displaying an Sql Image in a datagrid.
The code I use is:
<tbody>
#foreach (var e in #EntitiesResult.Entities)
{
<tr class="col-sm">
<td class="text-sm-center">
<img src="#(#e.Image != null ? (() => GetImage(e.Image)) : "img/no-camera-sign.jpg")" alt="" width="75">
</td>
<td class="text-sm-left">#e.IsahPrimKey</td>
<td class="text-sm-left">#e.ExtraInfo</td>
<td class="hidden-xs hidden-sm">#e.IsahTableName</td>
</tr>
}
</tbody>
So there is a table column showing images. The idea is if there isn't any image in the database stored on a specific row than a default image is shown (no_camera_sign.jpg). But if e.image is not null than a GetImage function is called. This function is called:
protected string GetImage(byte[]? image)
{
if (image != null)
{
return $"data:image/png;base64, {Convert.ToBase64String(image)}";
}
else
{
return string.Empty;
}
}
The problem is that this function is never fired and I don't understand. If the Image is null than the dummy image is shown. So that works but the GetImage function is never fired.
Can someone please explain how to do this...
This code is just wrong
<img src="#(#e.Image != null ? (() => GetImage(e.Image)) : "img/no-camera-sign.jpg")" alt="" width="75">
You are saying: if e.Image is not null return a lambda that - if something invoked it, would return an image... but there is nothing to call it, and it is probably just getting ToStringed.
Try just calling the GetImage method
<img src="#(e.Image != null ? GetImage(e.Image) : "img/no-camera-sign.jpg")" alt="" width="75">
Related
i have the following code here where i map data using map funtion the issue is that when
arrays are empty i get the flowing error
Cannot read properties of undefined (reading 'map')
i dont want error to occur
const Row = ([date, item], index) => {
return (
<tr className="gradiantblur" key={date || index}>
<td style={styles.tdFirst}>{date}</td>
{columns.map((each, i) => (
<td key={i} style={styles.td}>
{item.data &&
item.data[each] &&
item.data[each].map((itemByModule, id) => (
<span key={id}>
{itemByModule.submodule}
<br />
</span>
))}
</td>
))}
<td style={styles.td}>
{item.customs &&
item.customs.map((each, i) => (
<span key={i}>
{each.activity}
<br />
</span>
))}
</td>
</tr>
);
};
return (
<table style={{ width: "100%", borderCollapse: "collapse" }}>
<thead style={{ borderBottom: "5px solid #5c0048" }}>
<tr className="gradiantblur">
<th style={styles.th}>Dates</th>
{columns.map((each) => (
<th style={styles.th} key={each}>
{each}
</th>
))}
<th style={styles.th}>Custom</th>
</tr>
</thead>
<tbody>{Object.entries(data).map(Row)}</tbody>
</table>
);
}
show me some method where the ui displayes with out ging the error when there is no data
First thing to understand is that an empty array ([]) is not equal to undefined.
An empty array has all methods of arrays, while undefined doesn't.
There are a few ways to to get around the problem:
doing a columns && columns.map(..., shows nothing whenever your array is undefined, but maps through it whenever it is an array.
doing a columns ? columns.map(... : <div>no Data</div>, maps through array if it is truthy, otherwise shows other elements.
doing a (columns ?? []).map(..., always maps through an array, but actually first checks if columns is undefined, if it is, replaces it with an empty array.
Your columns is first undefined (before you set it with an other value). Instead of that, you should set it as an empty array initialy, like this:
const [columnns, setColumns] = useState([])
This way it will not be undefined
I'm adding a spacer tr after groups of related tr's in a React component. I'm rendering the rows via a map() function. I've added a property to the last item in the collection named IsLastItem. I'm trying to prevent the map() function from writing out a spacer row after the last item in the collection by using a guard condition at the end of the map() like this:
{ y && {!y.IsLastItem} (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
)}
However, the following runtime error is being thrown with this implementation:
y.IsLastItem is not a function
I've validated that the IsLastItem property does exist on the last item in the collection. Even if the IsLastItem property didn't exist on the last item, it seems like there shouldn't be any runtime errors since undefined would simply eval to false. Any idea what I might be doing wrong in this code?
You are using curly braces which are used for functions. That's why it is misleading that. You need to do it like:
{ y && y.IsLastItem && (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
)}
Hope this works for you.
You could try like this:
{ y && !y.IsLastItem &&
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
}
or
{ y && !y.IsLastItem ? (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
): null}
Best way is the 1st one.
If you have implemented the IsLastItem then you want
{ y && !y.IsLastItem (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
)}
Otherwise probably
items.map(item, index) => {
{ y && index >= items.length (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
)}
Your error is in your conditional. You used curly braces to surround your conditional: {!y.IsLastItem}, which is not the correct syntax for conditionals, and that is causing it to try to execute the block inside as a function. Remove the curly braces and add another && after the conditional before the block of code you want to return.
So it should be y && y.IsLastItem && (whatever JSX you want to return if it's the last item)
To only add the separator after the last item in the array of items, your .map statement might look something like this:
items.map(y => {
return (
<>
... # whatever your standard row component for y is
{y && y.IsLastItem && (
<tr>
<td colSpan={4} style={{height:25}}></td>
</tr>
)}
</>
)
})
I am trying to add pictures to a table where the user clicks a button and an image goes to the first cell, they press it again and the second image goes in the 2nd cell, and so on and so on. I was trying to do something like this:
<tr className = "tableRow">
<td><img src = {this.state.Array[0].image} alt = "" /></td>
<td><img src = {this.state.Array[1].image} alt = ""/></td>
<td><img src = {this.state.Array[2].image} alt = ""/></td>
</tr>
and then on the click of the button just push a new image to the state array. Of course I failed to realize that until the image was pushed to the array, Array[x] would be undefined and rendering would fail.
I figured I could just put empty strings in the array and then replace them with images, but I got this feeling that there was a much better way to go about doing this that I am missing.
Any suggestions are appreciated
You can use a conditional to only display the img element if the array length is large enough
<td>
{ this.state.Array.length > 0 ? <img src={this.state.Array[0]} alt="" />
: null }
</td>
Why not iterate over all of the images that are currently stored in the state, so that only the images that are in the array will be rendered, and as they are added or removed, the number of images will be updated.
Don't forget about including a unique key for each element though. You may have a better way of doing this, but for now I created keys based on the array index (not ideal).
return (
<tr className="tableRow">
{this.state.Array.map((image, index) => (
<td key={`td-${index}`}>
<img key={`img=${index}`} src={image.image} alt="" />
</td>
))}
</tr>
)
Can you explain me why react show warning Warning: validateDOMNesting(...): #text cannot appear as a child of <tr>. See Router > RouterContext > CarWashPage > AllCarWashTable > tr > #text.? I don't see any text inside tag tr
Code that renders table
export default class AllCarWashTable extends React.Component{
constructor(props) {
super(props);
this.generateHeaders = this.generateHeaders.bind(this);
this.generateRows = this.generateRows.bind(this);
};
static propTypes = {
cols : React.PropTypes.array.isRequired,
rows : React.PropTypes.array.isRequired
}
generateHeaders() {
let cols = this.props.cols; // [{key, label}]
return cols.map(function(colData) {
return <th key={colData.key}> {colData.label} </th>;
});
}
generateRows() {
let cols = this.props.cols, // [{key, label}]
data = this.props.rows;
if (this.props.rows.length > 0) {
return data.map(function(item) {
var cells = cols.map(function(colData) {
return <td key={colData.key}> {item[colData.key]} </td>;
});
return <tr key={item.id}> {cells} </tr>;
});
}
}
render(){
let headers = this.generateHeaders();
let rows = this.generateRows();
return (
<table className="table table-hove">
<thead>
<tr>
{headers}
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
)
}
}
At the end, my table has the following structure
Where is the problem?
The problem is the spaces in this line:
return <tr key={item.id}> {cells} </tr>;
It might seem silly, but you're actually rendering the cells and some whitespace (i.e. text). It should look like this:
return <tr key={item.id}>{cells}</tr>;
This will also happens when using logical AND short-circuit && to show/hide conditional rows:
{
foo && (<tr><td>{foo}</td></tr>)
}
change it to ternary a ? b : c form where c is null will fix it
{
foo ? (<tr><td>{foo}</td></tr>) : null
}
In my case where was an empty '' output (w\o space inside)
<tbody>
{this.props.orders.map(
order =>this.props.selectedAgent === order.agent ?
<Row item={order} key={ order._id } /> : ''
)
}
</tbody>
The null does the trick:
<tbody>
{this.props.orders.map(
order =>this.props.selectedAgent === order.agent ?
<Row item={order} key={ order._id } /> : null
)
}
</tbody>
The accepted answer wasn't the root cause in my case. I got the same warning when I had a comment after <th> tag. The warning went away when I removed the comment.
const TableHeaders = (props) => (
<tr>
<th>ID</th> {/* TODO: I had a comment like this */}
</tr>
)
EDIT: Removing the space between </th> and {/* will also do the trick.
A <tr> HTML tag indicates a table row. So, any text to be displayed inside a table row must be placed inside <td> HTML tag. This would remove the error.
Example:
return (
<tr>
<td> {/* Using <td> inside <tr> */}
Hello World!
</td>
</tr>
);
Notification warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of <tbody>. Make sure you don't have any extra white space between tags on each line of your source code.
In my case, initialize variable should NOT is null.
let elementCart = ''; {/* in the here,warning will append */}
if(productsCart.length > 0){
elementCart = productsCart.map((item, index) => {
return <CartItem item={item} key={index} index={index} />
});
}
return(
<tbody id="my-cart-body">
{elementCart}
</tbody>
)
Solution: let elementCart = null;
Incase anyone else comes across this error or a similar whitespace error with Material UI in React, my solution after hours of breaking my code was a simple javascript comment inside of my table.
{ /* sortable here */ }
I removed that from between my table elements and the warning disappeared.
Make sure the let variables are valued otherwise initialize a new empty array.
{headers ? headers : []}
or
{rows || []}
For me it works like a charm ...
render(){
let headers = this.generateHeaders();
let rows = this.generateRows();
return (
<table className="table table-hove">
<thead>
<tr>
{headers ? headers : []}
</tr>
</thead>
<tbody>
{rows || []}
</tbody>
</table>
)
}
also || null can solve it.
the important is that the value is not ''
Kevin Law (from other comment) said that you can do this:
{
foo ? (<tr><td>{foo}</td></tr>) : null
}
But you can also fix it like this:
{
Boolean(foo) && <tr><td>{foo}</td></tr>
}
Removing the comment is what helped me too
in my case initialize a variable with null instead of "" works fine
In addition to #Jarno's answer, I also ran into this issue as well. Double check that you don't have any additional } or { at the end of your javascript code:
{this.props.headers.map(header => <th key={header}>{header}</th>)}}
↑
I received this warning when I had a parenthesis instead of a curly bracket
<table>
<tbody>
<tr>
(showMsg && <td>Hi</td>} // leading '(' should be a '{'
</td>
</tbody>
</table>
I received this warning when I put text inside <tr> element with no <td> elements. I wrapped my text with <td> elements and the warning disappeared.
When I did this, having a whitespace in my text or having used {} didn't matter.
In my case I indeed had a <tr> inside a <tr> (intended to use <td>) :)
It's very easy to find. Just open your inspect and look for tag. It should appear at the beginning or at the end of the tag a quoted string like this:
You shouldn't pass an unexpected element in the table body tag. You should use tr and td
In your rows would return the element with tr and td
{rows}
Something like
return(
<tr>
<td>
Hello
</td>
</tr>
)
For my situation, I was getting this error because I forgot to update a SQL query to include an updated column name. The original query was trying to access a column that didn't exist.
This query was being used with Nextjs, React, Material UI and sent to a PostgreSQL server in order to load up a MUI front-end table with database information from the table.
Updating the query fixed the issue.
I have an array with items and I want to make something like this:
<tr>
(until have items in array
<td></td><td></td>)
</tr>
But if I do that, I get an JSXTransformer error :
Adjacent XJS elements must be wrapped in an enclosing tag
Working version:
{rows.map(function (rowElement){
return (<tr key={trKey++}>
<td className='info' key={td1stKey++}>{rowElement.row[0].value}</td><td key={td2ndKey++}>{rowElement.row[0].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[1].value}</td><td key={td2ndKey++}>{rowElement.row[1].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[2].value}</td><td key={td2ndKey++}>{rowElement.row[2].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[3].value}</td><td key={td2ndKey++}>{rowElement.row[3].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[4].value}</td><td key={td2ndKey++}>{rowElement.row[4].count}</td>
.......
</tr>);
})}
I tried this one. But with <div> enclosing tag it doesn't work fine.
Answer here:
Uncaught Error: Invariant Violation: findComponentRoot(..., ...$110): Unable to find element. This probably means the DOM was unexpectedly mutated
<tbody>
{rows.map(function (rowElement){
return (<tr key={trKey++}>
{rowElement.row.map(function(ball){
console.log('trKey:'+trKey+' td1stKey'+td1stKey+' ball.value:'+ball.value+' td2ndKey:'+td2ndKey+' ball.count:'+ball.count);
return(<div key={divKey++}>
<td className='info' key={td1stKey++}>{ball.value}</td><td key={td2ndKey++}>{ball.count}</td>
</div>);
})}
</tr>);
})}
</tbody>
Please, advise me how to properly wrap few TD tags!
I tried use a guide Dynamic Children, but JSXTransformer doesn't allow me do that.
The following error usually occurs when you are returning multiple elements without a wrapping element
Adjacent XJS elements must be wrapped in an enclosing tag
Like
return (
<li></li>
<li></li>
);
This doesn't work because you are effectively returning two results, you need to only ever be returning one DOM node (with or without children) like
return (
<ul>
<li></li>
<li></li>
</ul>
);
// or
return (<ul>
{items.map(function (item) {
return [<li></li>, <li></li>];
})}
</ul>);
For me to properly answer your question could you please provide a JSFiddle? I tried to guess what you're trying to do and heres a JSFiddle of it working.
When using the div as a wrapper its actually never rendered to the DOM (not sure why).
<tr data-reactid=".0.0.$1">
<td class="info" data-reactid=".0.0.$1.$0.0">1</td>
<td data-reactid=".0.0.$1.$0.1">2</td>
<td class="info" data-reactid=".0.0.$1.$1.0">1</td>
<td data-reactid=".0.0.$1.$1.1">2</td>
<td class="info" data-reactid=".0.0.$1.$2.0">1</td>
<td data-reactid=".0.0.$1.$2.1">2</td>
<td class="info" data-reactid=".0.0.$1.$3.0">1</td>
<td data-reactid=".0.0.$1.$3.1">2</td>
</tr>
EDIT: React 16+
Since React 16 you can now use fragments.
You would do it like this now
return <>
<li></li>
<li></li>
<>;
Or you can use <React.Fragment>, <> is shorthand for a HTML fragment, which basically is just a temporary parent element that acts as a container, once its appended to the document it no longer exists.
https://reactjs.org/docs/fragments.html
https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
So you have pairs of <td> elements which you want to return from a .map. The easiest way to do this is to just wrap them in an array.
<tr>
{data.map(function(x, i){
return [
<td>{x[0]}</td>,
<td>{x[1]}</td>
];
})}
</tr>
Don't forget the comma after the first </td>.
With the release of React 16, there is a new component called Fragment.
If are would like to return a collection of elements/components without having to wrap them in an enclosing element, you can use a Fragment like so:
import { Component, Fragment } from 'react';
class Foo extends Component {
render() {
return (
<Fragment>
<div>Hello</div
<div>Stack</div>
<div>Overflow</div>
</Fragment>
);
}
}
Here is how you will do it
<tbody>
{this.props.rows.map((row, i) =>
<tr key={i}>
{row.map((col, j) =>
<td key={j}>{col}</td>
)}
</tr>
)}
</tbody>