React Virtualized - Table Example - How do I make it work? - react-virtualized

I've been struggling to make this react virtualized table example work & seriously starting to doubt my sanity. I've created a react app and I'm just trying to render the example table inside App.js with this:
class App extends Component {
render() {
var data = [1,2,3,4,5,6,7,8,9,10];
return (
<TableExample
list={data}
/>
);
}
}
React keeps saying list isn't defined - it seems obvious I'm not getting the data into the component the right way. I haven't been able to understand the example code, what props need to be passed in and what they should be named. Sorry for the stupid question but I've been stuck forever not knowing where else to find an answer. The table example code is below:
/** #flow */
import Immutable from 'immutable';
import PropTypes from 'prop-types';
import * as React from 'react';
import {
ContentBox,
ContentBoxHeader,
ContentBoxParagraph,
} from '../demo/ContentBox';
import {LabeledInput, InputRow} from '../demo/LabeledInput';
import AutoSizer from '../AutoSizer';
import Column from './Column';
import Table from './Table';
import SortDirection from './SortDirection';
import SortIndicator from './SortIndicator';
import styles from './Table.example.css';
export default class TableExample extends React.PureComponent {
static contextTypes = {
list: PropTypes.instanceOf(Immutable.List).isRequired,
};
constructor(props, context) {
super(props, context);
const sortBy = 'index';
const sortDirection = SortDirection.ASC;
const sortedList = this._sortList({sortBy, sortDirection});
this.state = {
disableHeader: false,
headerHeight: 30,
height: 270,
hideIndexRow: false,
overscanRowCount: 10,
rowHeight: 40,
rowCount: 1000,
scrollToIndex: undefined,
sortBy,
sortDirection,
sortedList,
useDynamicRowHeight: false,
};
this._getRowHeight = this._getRowHeight.bind(this);
this._headerRenderer = this._headerRenderer.bind(this);
this._noRowsRenderer = this._noRowsRenderer.bind(this);
this._onRowCountChange = this._onRowCountChange.bind(this);
this._onScrollToRowChange = this._onScrollToRowChange.bind(this);
this._rowClassName = this._rowClassName.bind(this);
this._sort = this._sort.bind(this);
}
render() {
const {
disableHeader,
headerHeight,
height,
hideIndexRow,
overscanRowCount,
rowHeight,
rowCount,
scrollToIndex,
sortBy,
sortDirection,
sortedList,
useDynamicRowHeight,
} = this.state;
const rowGetter = ({index}) => this._getDatum(sortedList, index);
return (
<ContentBox>
<ContentBoxHeader
text="Table"
sourceLink="https://github.com/bvaughn/react-virtualized/blob/master/source/Table/Table.example.js"
docsLink="https://github.com/bvaughn/react-virtualized/blob/master/docs/Table.md"
/>
<ContentBoxParagraph>
The table layout below is created with flexboxes. This allows it to
have a fixed header and scrollable body content. It also makes use of{' '}
<code>Grid</code> for windowing table content so that large lists are
rendered efficiently. Adjust its configurable properties below to see
how it reacts.
</ContentBoxParagraph>
<ContentBoxParagraph>
<label className={styles.checkboxLabel}>
<input
aria-label="Use dynamic row heights?"
checked={useDynamicRowHeight}
className={styles.checkbox}
type="checkbox"
onChange={event =>
this._updateUseDynamicRowHeight(event.target.checked)
}
/>
Use dynamic row heights?
</label>
<label className={styles.checkboxLabel}>
<input
aria-label="Hide index?"
checked={hideIndexRow}
className={styles.checkbox}
type="checkbox"
onChange={event =>
this.setState({hideIndexRow: event.target.checked})
}
/>
Hide index?
</label>
<label className={styles.checkboxLabel}>
<input
aria-label="Hide header?"
checked={disableHeader}
className={styles.checkbox}
type="checkbox"
onChange={event =>
this.setState({disableHeader: event.target.checked})
}
/>
Hide header?
</label>
</ContentBoxParagraph>
<InputRow>
<LabeledInput
label="Num rows"
name="rowCount"
onChange={this._onRowCountChange}
value={rowCount}
/>
<LabeledInput
label="Scroll to"
name="onScrollToRow"
placeholder="Index..."
onChange={this._onScrollToRowChange}
value={scrollToIndex || ''}
/>
<LabeledInput
label="List height"
name="height"
onChange={event =>
this.setState({height: parseInt(event.target.value, 10) || 1})
}
value={height}
/>
<LabeledInput
disabled={useDynamicRowHeight}
label="Row height"
name="rowHeight"
onChange={event =>
this.setState({
rowHeight: parseInt(event.target.value, 10) || 1,
})
}
value={rowHeight}
/>
<LabeledInput
label="Header height"
name="headerHeight"
onChange={event =>
this.setState({
headerHeight: parseInt(event.target.value, 10) || 1,
})
}
value={headerHeight}
/>
<LabeledInput
label="Overscan"
name="overscanRowCount"
onChange={event =>
this.setState({
overscanRowCount: parseInt(event.target.value, 10) || 0,
})
}
value={overscanRowCount}
/>
</InputRow>
<div>
<AutoSizer disableHeight>
{({width}) => (
<Table
ref="Table"
disableHeader={disableHeader}
headerClassName={styles.headerColumn}
headerHeight={headerHeight}
height={height}
noRowsRenderer={this._noRowsRenderer}
overscanRowCount={overscanRowCount}
rowClassName={this._rowClassName}
rowHeight={useDynamicRowHeight ? this._getRowHeight : rowHeight}
rowGetter={rowGetter}
rowCount={rowCount}
scrollToIndex={scrollToIndex}
sort={this._sort}
sortBy={sortBy}
sortDirection={sortDirection}
width={width}>
{!hideIndexRow && (
<Column
label="Index"
cellDataGetter={({rowData}) => rowData.index}
dataKey="index"
disableSort={!this._isSortEnabled()}
width={60}
/>
)}
<Column
dataKey="name"
disableSort={!this._isSortEnabled()}
headerRenderer={this._headerRenderer}
width={90}
/>
<Column
width={210}
disableSort
label="The description label is really long so that it will be truncated"
dataKey="random"
className={styles.exampleColumn}
cellRenderer={({cellData}) => cellData}
flexGrow={1}
/>
</Table>
)}
</AutoSizer>
</div>
</ContentBox>
);
}
_getDatum(list, index) {
return list.get(index % list.size);
}
_getRowHeight({index}) {
const {list} = this.context;
return this._getDatum(list, index).size;
}
_headerRenderer({dataKey, sortBy, sortDirection}) {
return (
<div>
Full Name
{sortBy === dataKey && <SortIndicator sortDirection={sortDirection} />}
</div>
);
}
_isSortEnabled() {
const {list} = this.context;
const {rowCount} = this.state;
return rowCount <= list.size;
}
_noRowsRenderer() {
return <div className={styles.noRows}>No rows</div>;
}
_onRowCountChange(event) {
const rowCount = parseInt(event.target.value, 10) || 0;
this.setState({rowCount});
}
_onScrollToRowChange(event) {
const {rowCount} = this.state;
let scrollToIndex = Math.min(
rowCount - 1,
parseInt(event.target.value, 10),
);
if (isNaN(scrollToIndex)) {
scrollToIndex = undefined;
}
this.setState({scrollToIndex});
}
_rowClassName({index}) {
if (index < 0) {
return styles.headerRow;
} else {
return index % 2 === 0 ? styles.evenRow : styles.oddRow;
}
}
_sort({sortBy, sortDirection}) {
const sortedList = this._sortList({sortBy, sortDirection});
this.setState({sortBy, sortDirection, sortedList});
}
_sortList({sortBy, sortDirection}) {
const {list} = this.context;
return list
.sortBy(item => item[sortBy])
.update(
list => (sortDirection === SortDirection.DESC ? list.reverse() : list),
);
}
_updateUseDynamicRowHeight(value) {
this.setState({
useDynamicRowHeight: value,
});
}
}

Looking at some previous questions, it seems that the example is using some components that are not included inside dist package. Thats probably why you are getting undefined error.
Here is the most basic example of Tables in react virtulized:
import React from 'react';
import ReactDOM from 'react-dom';
import { Column, Table } from 'react-virtualized';
import 'react-virtualized/styles.css'; // only needs to be imported once
// Table data as an array of objects
const list = [
{ name: 'Brian Vaughn', description: 'Software engineer' }
// And so on...
];
// Render your table
ReactDOM.render(
<Table
width={300}
height={300}
headerHeight={20}
rowHeight={30}
rowCount={list.length}
rowGetter={({ index }) => list[index]}
>
<Column
label='Name'
dataKey='name'
width={100}
/>
<Column
width={200}
label='Description'
dataKey='description'
/>
</Table>,
document.getElementById('example')
);
When learning new library, its always best to start with the most simple example then expand on it. Here is the link to the full table docs.

The issue with the example is that in order for contextTypes to work, the parent component needs to define corresponding contextTypes and a getChildContext function.
In the parent component:
class App extends React.Component {
static childContextTypes = {
list: PropTypes.instanceOf(Immutable.List).isRequired
};
getChildContext() {
return {
list
};
}
render() {
return <TableExample />;
}
}
Mentioned in this issue; see lines 48-53 and 68-76 of the react-virtualized demo Application.js.

Related

Filtering locally rendered JSON table in React

I have a page in my React App that renders some locally stored JSON Data into a table. I've been trying for a long time to implement a search bar that will filter through the PostCode column in the table and return the row. So far I've been able to make a search bar that does what I want it to but I haven't been able to integrate it into the page with the table.
My apologies if this is an easy question or I'm way off the mark. I'm a coding novice but have to use React for a project and struggle to get to grips with it.
The code for my table looks like this:
import SearchBar from './SearchBar'
import React,{useState,useEffect} from 'react';
import './App.css';
import { Data } from './NewData.js'
export const JsonReader = () => {
return (
<>
<ArchiveHeader />
<div className="data-container">Welcome to RF</div>
{Data.map((data, key) => {
return (
<div key={key}>
<JsonTable
key = {key}
Username = {data.Username}
Address = {data.Address}
PostCode = {data.PostCode}
Details ={data.Details}
Date ={data.Date}
Score ={data.Score}
/>
</div>
);
})}
</>
);
};
const ArchiveHeader = () => {
return (
<header className="ArchiveHeader">
<h2>Rent Flag</h2>
</header>
);
};
const JsonTable= ({ Username, Address, PostCode, Details, Date, Score }) => {
if (!Username) return <div />;
return (
<table data={Data}>
<tbody>
<tr>
<td>
<h5>{Username}</h5>
</td>
<td>
<h5>{Address}</h5>
</td>
<td>
<h4>{PostCode}</h4>
</td>
<td>
<p>{Details}</p>
</td>
<td>
<p>{Date}</p>
</td>
<td>
<p>{Score}</p>
</td>
</tr>
</tbody>
</table>
);
};
export default JsonReader;
and the code for my searchbar looks like this:
import Papa from "papaparse";
import React, { useState, useEffect } from 'react';
import { Data } from './NewData.js'
import JsonReader from './JsonReader'
export default function SearchBar () {
const [searchTerm,setSearchTerm] = useState('')
return (
<div className="SearchBar">
<input type="text" placeholder="search..." onChange={e=>setSearchTerm(e.target.value)} />
{Data.filter((val)=>{
if(searchTerm == ""){
return val
}
else if(val.PostCode.toLowerCase().includes(searchTerm.toLowerCase())){
return val;
}
}).map((val,key)=>{
return <div>{val.PostCode} </div>
})}
</div>
);
}
You can use useMemo hook for this functionality.
const searchResults = useMemo(() => {
if (!searchTerm) {
return items;
}
return Data?.filter((item) =>
item?.toLowerCase()?.includes(searchTerm?.toLowerCase().trim())
);
}, [Data, searchTerm]);
You can use searchResults variable and render that in your table.
In the same JsonReader function you should:
Create the useState constants [searchTerm, setSearchTerm].
Set a new FData array with filtered data and that is the one you should do the mapping to.
Place the input field on the same page.
And, instead of using the Data.map you will use the FData.map.
This is how your JsonReader function should look like (and the SearchBar function could be discarded):
export const JsonReader = () => {
const [searchTerm, setSearchTerm] = useState("");
const FData = Data.filter((val) => {
if (searchTerm == "") {
return val;
} else if (val.PostCode.toLowerCase().includes(searchTerm.toLowerCase())) {
return val;
}
});
return (
<>
<ArchiveHeader />
<div className="data-container">Welcome to RF</div>
<input type="text" placeholder="search..." onChange={(e) => setSearchTerm(e.target.value)} />
{FData.map((data, key) => {
return (
<div key={key}>
<JsonTable
key = {key}
Username = {data.Username}
Address = {data.Address}
PostCode = {data.PostCode}
Details ={data.Details}
Date ={data.Date}
Score ={data.Score}
/>
</div>
);
})}
</>
);
};

Problem with Select mui and Object value dissapears

I feel like I am very close to fixing it but when I change select option the selected values disappear. How can I avoid this when using Objects in MUI select?
Code Sandbokx: https://codesandbox.io/s/jovial-pascal-ngpgyh?file=/src/App.js:0-909
import { useState } from "react";
import "./styles.css";
import { TextField, MenuItem } from "#material-ui/core";
export default function App() {
const mainOptions = [
{ id: 1, text: "hello" },
{ id: 2, text: "This is just a test" }
];
function handleFilterChange(e) {
console.log(e.target);
setChosenFilterId(e.target.value);
}
const [chosenFilterId, setChosenFilterId] = useState(0);
return (
<>
<TextField
select
label="Category"
value={mainOptions[chosenFilterId].text}
onChange={(e) => handleFilterChange(e)}
>
{mainOptions.map((option, index) => {
return (
//When i try to change value={option} to value={index} I also get another error
<MenuItem value={option} key={index}>
{option.text}
</MenuItem>
);
})}
</TextField>
</>
);
TextField's value and MenuItem's value couldn't be an Object, and both should be the same kay.
So,
<TextField
select
label="Category"
value={chosenFilterId} // <= here
onChange={(e) => handleFilterChange(e)}
>
{mainOptions.map((option, index) => {
return (
<MenuItem value={option.id} key={index}> {/* <= here */ }
{option.text}
</MenuItem>
);
})}
</TextField>
Demo: https://codesandbox.io/s/immutable-star-ppzgzl?file=/src/App.js

'DELETE' 'Title' does not delete the 'title' row 'sub-title, count'; but shows 'title' row again with the 'totalcount' - ReactJS

I have a table which contains Title, Sub-Title and TotalCount. sub-title is the child of title. So, in the collection of title, objectId of sub-title is saved in the database. Below is the screenshot of the table.
Title contains Kilo , Test and Grams with it's respective sub-title and totalcount
What happens is, suppose I delete row Title with Test. Once hit delete, I should get records that are Kilo and Grams. But I don't get that. In fact, I get row with Test with deleted sub-title as blank and the totalcount which adds up all the previous count and displays 4.
The same problem arises when I delete Title Grams.
Below is the code related to the issue
mainPage.js
import React,{ Component } from 'react';
import { connect } from 'react-redux';
import Grid from '#material-ui/core/Grid';
import TabPanel from '../../utils/TabPanel';
import { mainStructure, deleteDbData } from './actions';
import TitleSubtitleTable from './titlesubtitletable';
class MainPage extends Component {
constructor() {
super();
this.state = { filter: {} };
}
componentDidMount() {
this.getData();
}
getData = async () => {
let data = {
data: {
title:
this.state.filter && this.state.filter.title
? this.filter.title
: null,
subtitle:
this.state.filter && this.state.filter.subtitle
? this.state.filter.subtitle
: null,
},
};
await this.props.mainStructure(data);
};
deleteData = async (title) => {
let payload = {
type: title.type,
id: title._id,
};
await this.props.deleteDbData(payload);
await this.getData();
};
render() {
return (
<div>
<Grid>
<TabPanel>
{this.props.structure.tablestructure.data ? (
<TitleSubtitleTable
records={this.props.structure.tablestructure.data}
totalCount={this.props.structure.tablestructure.totalCount}
handleDelete={this.deleteData}
/>
) : null}
</TabPanel>
</Grid>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
structure: state.structure,
};
};
export default connect(mapStateToProps, { mainStructure, deleteDbData })(
MainPage
);
Below is code for titlesubtitletable.js
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import DeleteIcon from '#material-ui/icons/Delete';
import Avatar from '#material-ui/core/Avatar';
import IconButton from '#material-ui/core/IconButton';
const columns = [
{ id: 'title', label: 'Title' },
{ id: 'delete', label: '' },
{ id: 'subtitle', label: 'Sub-Title' },
{ id: 'count', label: 'Total Count' },
];
function EnhancedTableTitle() {
return (
<TableHead>
<TableRow>
{columns.map((titleCell) => (
<TableCell key={titleCell.id}> {titleCell.label} </TableCell>
))}
</TableRow>
</TableHead>
);
}
export default function EnhancedTable(props) {
return (
<div>
<TableContainer>
<Table>
<EnhancedTableTitle />
<TableBody>
{props.records.map((row, index) => {
return row.children.length > 0 ? (
row.children.map((title) => (
<TableRow key={index}>
<TableCell> {row.name} </TableCell>
<TableCell>
<IconButton onClick={() => props.handleDelete(row)}>
<Avatar>
<DeleteIcon color='action' />
</Avatar>
</IconButton>
</TableCell>
<TableCell align='left' className={classes.tableCellSmall}>
{title.name}
</TableCell>
<TableCell align='left' className={classes.tableCellSmall}>
<IconButton onClick={() => props.handleDelete(title)}>
<Avatar>
<DeleteIcon color='action' />
</Avatar>
</IconButton>
</TableCell>
<TableCell>{title.count}</TableCell>
</TableRow>
))
) : (
<TableRow key={index}>
<TableCell>{row.name} </TableCell>
<TableCell>
<IconButton onClick={() => props.handleDelete(row)}>
<Avatar>
<DeleteIcon color='action' />
</Avatar>
</IconButton>
</TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell>{row.count}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</div>
);
}
Brief Explanation: I do not want the deleted record to be seen again when I try to delete Title. If 3 different titles, and delete one title, the result should be 2 titles and not the 3 which adds up and shows totalcount
I don't know where I am going wrong. Really need help to figure out the problem. Thank you!!

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. With HOC

I've implemented an HOC that hide a component if the user hasn't subscribed,after that, i got that red error that I can't understand.
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
Here is the HOC :
const withSubscription = <P extends object>(
BaseComponent: ComponentType<P>,
pack: Pack,
): ((props: P) => ReactElement | null) => (props: P): null | ReactElement => {
const { subscription } = useSubscription();
const subscriptionIndex = useMemo(() => subscription?.findIndex((subscriptionPack) => subscriptionPack === pack), [pack]);
if (subscriptionIndex === -1) {
return null;
}
return <BaseComponent {...props} />;
};
I've applied the HOC to a button :
const Button: FC = (props) => {
return (
<TouchableOpacity
style={[
styles.cartButtonContainer,
{ backgroundColor: primaryColor },
]}
onPress={handleAddProduct}
>
<Icon
name={"cart-arrow-down"}
materialCom
style={{ marginRight: 0 }}
size={25}
color={secondaryColor}
/>
</TouchableOpacity>
);
};
export default withSubscription(CartButton, Pack.CLICK_COLLECT);
And here is how I call it :
return (
<Button onPress={...}/>
)
There is something i'm doing wrong ?

react bootstrap grouplist renders badly on mobile chrome

i have a React App which worked fine, both on mobile and pc.
i am using 'react-bootstrap' listgroup and modal inside a material-ui tabs component.
it all worked fine until a few days ago on mobile the modal stopped rendering and the list items started to wrap instead of filling the entire witdh of the screen.
on pc chrome works fine, if i activate in VS Code chrome debugger the issue appears.
my code added below:
CatalogListItem.js
import React,{ Component } from 'react';
import {ListGroupItem} from 'react-bootstrap';
class CatalogListItem extends Component {
render() {
return (
<ListGroupItem bsStyle={(this.props.catalogItem.isCount)? null :"danger"}
align="right"
header={this.props.catalogItem.itemName + " - " + this.props.catalogItem.measureId.measureName}
onClick={() => {this.props.onClickHandler(this.props.catalogItem)}}
>
<img src={this.props.catalogItem.itemPicPath}
height="70" width="70" alt="item" align="left" />
<br/>
<span align="right">
מלאי קבוע: {this.props.catalogItem.itemStock} ,
מחיר: {this.props.catalogItem.itemPrice[0].price} ש"ח
פיקדון: {this.props.catalogItem.itemDeposit} ש"ח
<br/>
הנחה: {this.props.catalogItem.itemDiscount}%,
הנחה צוברת: {this.props.catalogItem.additionalDiscount}%
</span>
</ListGroupItem>
);
}
}
export default CatalogListItem;
CatalogTabs.js
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import React,{Component} from 'react';
import {Tabs,Tab} from 'material-ui/Tabs';
import {List} from 'material-ui/List';
import PropTypes from 'prop-types';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import ContentAdd from 'material-ui/svg-icons/content/add';
import CatalogListItem from '../catalogPage/CatalogListItem';
import CatalogItemFormModal from './CatalogItemFormModal';
// eslint-disable-next-line
const propTypes = {
//tabsTitles: PropTypes.object.isRequired,
pathName: PropTypes.string.isRequired
};
const fabStyle = {
bottom: 20,
left: 10,
position: 'fixed'
};
const emptyCatalogItem = {
"itemId": "",
"itemName": "",
"supplierId": {},
"measureId": {},
"itemStock": 0,
"itemPrice": [{price:0}],
"itemDeposit": 0,
"itemDiscount": 0,
"additionalDiscount": 0,
"itemPicPath": "http://freevector.co/wp-content/uploads/2012/04/70626-label-
beer-bottle.png",
"isCount": true
}
class CatalogTabs extends Component {
constructor(props) {
super(props);
this.state = {focusedCatalogItem:emptyCatalogItem,
showModal:false};
}
showModal(catalogItem){
this.setState({focusedCatalogItem:JSON.parse(JSON.stringify(catalogItem))});
this.setState({showModal: true});
}
hideModal(){
this.setState({showModal: false});
}
Listitemsfactory(supplier){
return(
<div>
{ this.props.catalogData.catalog
.sort((a, b) => a.itemName.localeCompare(b.itemName))
.map((catalogItem)=> {
if (supplier._id === catalogItem.supplierId._id)
return <CatalogListItem key={catalogItem._id}
catalogItem={catalogItem}
onClickHandler=
{this.showModal.bind(this)} />
return false;
}
)}
</div>);
}
render(){
return(
<div>
<MuiThemeProvider>
<Tabs>
{this.props.suppliersData.suppliers.map((supplier)=>
<Tab label={(supplier.supplierName.length > 6)?
supplier.supplierName.substring(0,6)+"..."
:
supplier.supplierName}
key={supplier._id}>
<List>
{this.Listitemsfactory(supplier)}
</List>
</Tab>
)}
</Tabs>
<FloatingActionButton onClick={()=>this.showModal(emptyCatalogItem)}
style={fabStyle}>
<ContentAdd/>
</FloatingActionButton>
</MuiThemeProvider>
<CatalogItemFormModal
suppliers={this.props.suppliersData.suppliers}
measures={this.props.measuresData}
heading={"פרטי פריט"}
onItemNameChange={this.onItemNameChange.bind(this)}
onItemSupplierChange={this.onItemSupplierChange.bind(this)}
onItemMeasureChange={this.onItemMeasureChange.bind(this)}
onItemPriceChange={this.onItemPriceChange.bind(this)}
onItemDepositChange={this.onItemDepositChange.bind(this)}
onItemDiscountChange={this.onItemDiscountChange.bind(this)}
onAdditionalDiscountChange={this.onAdditionalDiscountChange.bind(this)}
onItemStockChange={this.onItemStockChange.bind(this)}
onIsCountChange={this.onIsCountChange.bind(this)}
onItemDelete={this.startDeleteItem.bind(this)}
itemData = {this.state.focusedCatalogItem}
showModal={this.state.showModal}
onHide={this.hideModal.bind(this)}
onOk={this.startUpdateItem.bind(this)}/>
</div>
);}
onItemNameChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.itemName = newValue;
this.setState({focusedCatalogItem:item});
}
onItemSupplierChange(event, key, payload){
let item = this.state.focusedCatalogItem;
item.supplierId._id = payload;
this.setState({focusedCatalogItem:item});
}
onItemMeasureChange(event,key,payload){
let item = this.state.focusedCatalogItem;
item.measureId._id = payload;
this.setState({focusedCatalogItem:item});
}
onItemPriceChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.itemPrice = newValue;
this.setState({focusedCatalogItem:item});
}
onItemDepositChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.itemDeposit = newValue;
this.setState({focusedCatalogItem:item});
}
onItemDiscountChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.itemDiscount = newValue;
this.setState({focusedCatalogItem:item});
}
onAdditionalDiscountChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.additionalDiscount = newValue;
this.setState({focusedCatalogItem:item});
}
onItemStockChange(event,newValue){
let item = this.state.focusedCatalogItem;
item.itemStock = newValue;
this.setState({focusedCatalogItem:item});
}
onIsCountChange(isInputChecked){
let item = this.state.focusedCatalogItem;
item.isCount = isInputChecked;
this.setState({focusedCatalogItem:item});
}
startUpdateItem(catalogItem){
console.log("item that is sent to server:" +
JSON.stringify(catalogItem));
let catalogForSend = JSON.parse(JSON.stringify(catalogItem));
catalogForSend.supplierId = catalogItem.supplierId._id;
catalogForSend.measureId = catalogItem.measureId._id;
console.log("item that is sent to server:" +
JSON.stringify(catalogForSend));
this.props.updateCatalogItem(catalogForSend);
}
startDeleteItem(catalogItem){
this.props.deleteCatalogItem(catalogItem);
}
}
export default CatalogTabs;
CatalogPage.js
import React, { Component } from 'react';
import {bindActionCreators} from 'redux';
import {connect,} from 'react-redux';
import { ToastContainer } from 'react-toastify';
import Header from '../common/Header';
import CatalogTabs from './CatalogTabs';
import LoadingIndicator from '../common/Loading';
import {setFocusedCatalogItem,updateCatalogItem,deleteCatalogItem} from
'../../store/actions/catalogActions'
// this class detirme what page to display - cataloglist or an item form
// this is decided by the url - if provided an item id or not
class CatalogPage extends Component {
render() {
return (
<div>
<Header pageTitle="קטלוג"
isUserLoggedIn = {this.props.userData.isUserLoggedIn}/>
<CatalogTabs
pathName={this.props.location.pathname}
catalogData = {this.props.catalogData}
suppliersData = {this.props.suppliersData}
measuresData = {this.props.measuresData.measures}
userData = {this.props.userData}
setFocusedCatalogItem={this.props.setFocusedCatalogItem}
updateCatalogItem={this.props.updateCatalogItem}
deleteCatalogItem={this.props.deleteCatalogItem}/>
<LoadingIndicator isLoading =
{this.props.catalogData.fetchingCatalogData}/>
<ToastContainer/>
</div>
);
}
}
function mapStateToProps(state){
return{
userData: state.userData,
catalogData: state.catalogData,
suppliersData: state.suppliersData,
measuresData: state.measuresData
}
}
function matchDispachToProps(dispatch){
return bindActionCreators({setFocusedCatalogItem:setFocusedCatalogItem,
updateCatalogItem:updateCatalogItem,
deleteCatalogItem:deleteCatalogItem},dispatch)
}
export default connect(mapStateToProps,matchDispachToProps)(CatalogPage);

Resources