React with Kendo-ui Grid - Wrong column header - json

I have a React application using redux as state manager. In this application we are deciding to use Kendo Ui grids. The first test is Ok but we noticed that the columns are totally wrong. We define only 5 Columns to be displayed in the table but we noticed that all the columns from the json object get displayed. For example in the render method I have this code:
render() {
return (
<div>
<Grid
style={{ height: '400px' }}
data={this.state.gridData}
>
<Column field="ProductID" title="ID" width="40px" />
<Column field="ProductName" title="Name" width="250px" />
<Column field="Category.CategoryName" title="CategoryName" />
<Column field="UnitPrice" title="Price" width="80px" />
<Column field="UnitsInStock" title="In stock" width="80px" />
</Grid>
</div>
);
}
which should show only:
ID | Name | CategoryName | Price | In stock
but what it renders are those headers:
ProductID | ProductName | SupplierID | CategoryID | UnitPrice | UnitsInStock
which are the from the json object directly:
"ProductID " : 1,
"ProductName" : "Chai",
"SupplierID" : 1,
"CategoryID" : 1,
"UnitPrice" : 18.0000,
"UnitsInStock" : 39
In other words, no matter which columns I define (as <Column /> tag), the grid shows always the json field as column headers.
Following libs are imported:
import { Grid, GridColumn as Column, GridCell } from '#progress/kendo-react-grid';
I'm using exactly the exmaple from this page:
https://www.telerik.com/kendo-react-ui/components/grid/
There is no error in the console, so it is hard to find whats going on.
Any idea?
Update:
I added this console.log statement and i see that the columns are empty:
constructor(props: IProps) {
super(props);
this.state = { producuts: [{ ProductID: 'Cindy', ProductName: 'Jones', UnitPrice: 'cindy.jones#telerik.com' }]
};
this.grid = null;
}
render() {
return (
<div>
<Grid
data={this.state.producuts}
reorderable={true}
ref={(g) => { this.grid = g; }}
>
<GridColumn field="ProductID" title="ID" />
<GridColumn field="ProductName" title="Name" />
</Grid>
<button onClick={() => {
console.log(this.grid);
console.log(JSON.stringify(this.grid.columns));
}}>
log current properties into browser console.
</button>
</div>
);
}
This line console.log(JSON.stringify(this.grid.columns)) has always empty array result []
Although the headers should be:
ID | Name
but they appear like this:

I recently had the same problem. We are using 'react-hot-loader' which leads to your described error.
In the source code of the grid is a type comparison:
this.initColumns(children.filter(function (child) { return child && child.type === GridColumn; }));
When using react-hot-loader a Column is not of type GridColumn, but of type Proxycomponent. So the type check fails and the grid renders the default columns.
Workaround:
reactHotLoader.disableProxyCreation = true;
var grid = (<KendoGrid data={ { data: this.state.Products, total: 1} }
pageable={true} >
<KendoColumn field="ProductName" title="Product Name" />
<KendoColumn field="UnitPrice" title="Unit Price" format="{0:c}" width="120px" />
<KendoColumn field="UnitsInStock" title="Units In Stock" width="120px" />
<KendoColumn field="Discontinued" width="120px" />
</KendoGrid>);
reactHotLoader.disableProxyCreation = false;
Disabling the proxy creations solves the problem, but this workaround is quite dirty.
We disabled react-hot-loader in our project to solve this issue.

Related

How to Implement a search function in reactJS using MaterialUI

I try to develop a pokedex using the pokeapi. For now it works fine, the pokemon are fetched correctly and are displayed in a container. Now i want to implement a function to search and filter the pokemon. Therefore i used MaterialUI to put a searchBar on top of the App.
The fetched pokemon are given from App.js to my Component PokemonList which maps the data. My idea is now to filter the pokemonData before it is given to PokemonList to map only the pokemon i am looking for. But here i am stuck. I have no idea how to connect the search function with my pokemonData Hook from App.js . Can you help me?
This is my searchBar Component:
const SearchAppBar = () => {
const [search, setSearch] = useState("");
console.log(search)
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" sx={{ bgcolor: "black"}}>
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
<img src={logo} alt="logo" width="150" height="auto" />
</Typography>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
onChange={(e) => setSearch(e.target.value)}
id = 'searchbox'
placeholder="Search for Pokémon..."
inputProps={{'aria-label': 'search'}}
/>
</Search>
</Toolbar>
</AppBar>
</Box>
);
}
export default SearchAppBar;
you should save the entered value from input into a state and filter your data based on that state

conditional rendering not acting uniformly in reactjs?

I have used conditional rendering in the past but for some reason, it's working on one element here but not on another although they are both using the same JSON phrasing and the same type of conditional rendering?
JSON array
//Adobe component data
export default[
{
workName: 'Switch up your "Grub" Motiongraphic',
workDescription: 'This is a motion graphic comparing the environmental and health effects of consuming animal products compared to insects as dietary source of protein.',
workTech: ['Adobe After effects'],
videoAddress: ['https://youtu.be/cloat51hzDY'],
Images: []
},
{
workName: 'Simplyfit concept poster',
workDescription: 'This is a poster developed explaining the concept of Simplyfit, a fitness application developed as part of my final year project.',
workTech: ['Adobe Illustrator'],
videoAddress: [],
Images: ['SFPoster.jpg'],
},
{
workName: 'Switch up your "Grub" Infographic',
workDescription: 'This is an infographic developed explaining the benefits of consuming insects as a source of protein.',
workTech: ['Adobe Illustrator'],
videoAddress: [],
Images: ['insectMotiongraphic.png'],
},
{
workName: 'Crunchy Nut Advert spoof',
workDescription: 'This video was made as a comedic spoof of a Crunchy Nut advert',
workTech: ['Adobe Premier Pro'],
videoAddress: ['https://youtu.be/y8S2RUYrLN8'],
Images: [],
},
{
workName: 'Icons and Designs',
workDescription: 'These are a selection of logos and icons created by me.',
workTech: ['Adobe Premier Pro'],
videoAddress: [],
Images: ['Mylogo.png'],
},
]
The problem I'm having is with the 'videoAdress' and the 'Images' I've tried setting null values undefined etc for them both but for the images the only thing that stops them from rendering is setting the value as [] but this doesn't work for the videoAdress the iframe is still rendered?
React js code
{Data.map((Projects, index) => {
return <div className='Cards'>
<Carousel showThumbs={false} infiniteLoop={true} swipeable={false} emulateTouch={false} showStatus={false} autoPlay={slideShow} dynamicHeight={false}>
{Projects.Images && Projects.Images.map((Image, index) => { return <div className='image-iframeContainer'><img src={require("../assets/Port-images/Adobe/" + Image)} /></div> })}
{Projects.videoAddress && <div className='image-iframeContainer'><ReactPlayer url={Projects.videoAddress} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} /></div>}
</Carousel>
{Projects.webAddress && <div className='webButton'><LinkIcon onClick= { () => {window.open(Projects.webAddress);}}/></div>}
<h1>{Projects.workName}</h1>
{Projects.workTech.map((Tech, index) => { return <p className='techList'>{Tech}</p> })}
<div className='descriptionContainer'>
<p className='description'>{Projects.workDescription}</p>
</div>
</div>
})}
The function I would like is for the Images and Videos only to render if there is a stored address I'm sure I'm missing something very silly but still, I've been stuck on this for awhile.
Conditional rendering works by casting the condition to a truthy value. For example:
Projects.Images && <Component />
is equal to this:
!!Project.Images && <Component />
Now if you do this for an empty array [], the truthy value is TRUE. This means that <ReactPlayer /> is rendered with [] value and the <img /> is not rendered because [].map() doesn't run on an empty array.
To fix this do this instead:
{Projects.Images && Projects.Images.length > 0 && Projects.Images.map((Image, index) => {
return <div className='image-iframeContainer'>
<img src={require("../assets/Port-images/Adobe/" + Image)} />
</div>
})}
{Projects.videoAddress && Projects.videoAddress.length > 0 &&
<div className='image-iframeContainer'>
<ReactPlayer url={Projects.videoAddress[0]} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} />
</div>}
I noticed that your videoAddress doesn't use the map() method, but I guess it's a typo

Sorting Columns With BlueprintJS Table

I want to be able to sort my column based on ascending or descending numbers. I don't totally understand the way to do this. The online documentation shows that a Menu must be added to the table, but how does the menu know to affect which column.
This is the current way I have my BluePrintJS table implemented. I want to make the values sortable ascending or descending for any column
<Table enableFocusedCell="true" numRows=10 class="bp3-html-table bp3-table-resize-horizontal">
<Column
columnHeaderCellRenderer={() => (
<ColumnHeaderCell name="Name" />
)}
cellRenderer={i => (array.data[i] ? (<Cell>{array.data[i].name}</Cell>)
: (<Cell />))
}
/>
<Column
columnHeaderCellRenderer={() => (
<ColumnHeaderCell name="Ins" />
)}
cellRenderer={i => (array.data[i] ? (<Cell>{array.data[i].ins}</Cell>
) : (<Cell />))
}
/>
</Table>

onClick not propagated

I'm having troubles with creating a simple gallery allowing to print pictures. I constructed the interface. When I click on the print button, I'm not able to propagate event to a function. Funny enough, it always works for just a couple of items in the gallery so that console logs foo. Could you please point me where is the problem? I am using material-ui, tileData is a json with image url etc...
Many thanks!
class Galery extends React.Component {
state = {
tileData: tileData
};
printThis = tile => {
console.log("printing tile... " + tile.target.value);
};
render() {
const classes = this.props;
return (
<div className={classes.root}>
<ButtonAppBar />
<div style={{ marginBottom: 20 }} />
<Grid container spacing={8}>
<Grid item xs={10}>
<GridList
cellHeight={250}
cellWidth={250}
cols={5}
spacing={4}
className={classes.gridList}
>
{tileData.map(tile => (
<GridListTile key={tile.img}>
<img src={tile.img} alt={tile.title} />
<GridListTileBar
title={tile.title}
subtitle={<span>by: {tile.author}</span>}
actionIcon={
<IconButton
className={classes.icon}
value="foo"
onClick={this.printThis}
>
<i className="material-icons md-24 md-light">print</i>
</IconButton>
}
secondActionIcon={
<IconButton className={classes.icon}>
<i className="material-icons md-24 md-light">delete</i>
</IconButton>
}
/>
</GridListTile>
))}
</GridList>
</Grid>
<Grid item xs={2}>
<div className={classes.stats}>
<StatsTable />
</div>
</Grid>
</Grid>
</div>
);
}
}
It works for me to access the object id through event.currentTarget as per github answer here https://github.com/mui-org/material-ui/issues/7974#issuecomment-329250974
`
So my implementation is:
printThis = (event) => {
console.log('printing tile... '+ event.currentTarget.id);
};
<IconButton className={classes.icon} id = {tile.img} onClick={this.printThis}>
<i className="material-icons md-24 md-light" >
print
</i>
</IconButton>

How to make a react component that is a table with different sized columns and rows

I'm trying to make this into a react component so I can use it in my website:
I don't know how to go about making this or, if any libraries are involved, I don't know which ones.
it looks like this component will take a few properties:
const CardsDisplay = ({numCards}) => { /* ... */ }
const AvatarDisplay = ({imageUrl, numCards, name, score, popupMenu }) =>
<div style={{textAlign: 'center'}}>
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<img src={imageUrl} />
<CardsDisplay numCards={numCards} />
</div>
{name}
<br />
{score.toLocaleString()}
<popupMenu style={{float: 'right'}} />
</div>