Related
I have a table where I am feeding data into it from an api, the data is fetched correctly and displays properly for the table row and data which is part of the tbody but inside the thead I try to display a header but nothing seems to be displayed even though the data being passed to the header is being logged to the console. Can anyone see my issue?
Component with table:
import React, {useState, useEffect} from 'react';
import secondsToMinutes from '../utils/utils';
function Table(props) {
const styles = {
div: {
width: 'auto',
height: 'auto',
margin: '0 auto',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
},
};
const [table, setTable] = useState();
useEffect(() => {
setTable(<table >
<thead>
<tr>
{props.headerData.map(header => {
console.log("table header = ", header);
{header.map((item, i) => {
console.log("header item", item.name)
return (<th
} key={i}>{item.name}</th>
)})}
})}
</tr>
</thead>
<tbody>
{props.data.map((array, index) => (
<tr key={index}>
{array.map((item, i) => {
return (
<tr>
<td key={i}>{item.nameValue} </td>
</tr>
)
})}
</tr>
))}
</tbody>
</table>)
}, [props.data, props.header]);
return (
<div style={styles.div}>
{table}
</div>
)
}
export default Table;
You're not returning anything from the outer map().
Change the thead to:
<thead>
<tr>
{
props.headerData.map(header => {
console.log("table header = ", header);
return header.map((item, i) => {
console.log("header item", item.name)
return (<th key={i}>{item.name}</th>)
})
}}
}
</tr>
</thead>
Note the return before header.map
That said, you shouldn't save the DOM element to the useState. Rather save the data to the state, and then in your return render function render the table
I am running into an issue with trying to render a table in react using react table. I've narrowed the error down to the data variable around line 13 in figure 1.
When I hard code the data, as shown in figure 1, I have no issues and everything works fine. This hard coded array is a direct copy of the baselineData prop being passed into the PrectionsTable component.
My error only happens when the data object is changed to as shown in figure 2. Instead of the data being hard coded, I am spreading the baselineData prop data.
Figure 3 shows baselineData in react web dev tools and is in fact an array of objects located on the PredictionsTable.
The specific error I am making can be seen in figure 4.
Figure 1
import { useTable } from 'react-table';
import React from 'react';
import SpinnerCustom from '../Spinner.js';
export default function PredictionsTable({
predictions,
baselineData,
loading,
}) {
const checkIfValueIsNumberAndRound = (x) =>
typeof x === 'number' ? x.toFixed(2) : 'n/a';
const data = React.useMemo(() => {
return [
{
make_cut: 0.837075,
player_name: 'Finau, Tony',
top_10: 0.42559600288600297,
top_20: 0.5817631080031079,
top_5: 0.293940416666667,
win: 0.105025,
},
{
make_cut: 0.71215,
player_name: 'Day, Jason',
top_10: 0.228348582528583,
top_20: 0.366261590839716,
top_5: 0.136055932539683,
win: 0.0341,
},
{
make_cut: 0.719925,
player_name: 'Harman, Brian',
top_10: 0.223825056748807,
top_20: 0.366779750145688,
top_5: 0.12981958333333302,
win: 0.032675,
},
{
make_cut: 0.710225,
player_name: 'Montgomery, Taylor',
top_10: 0.21918973443223397,
top_20: 0.352992788086097,
top_5: 0.130785406746032,
win: 0.0324,
},
];
}, [baselineData]);
const columns = React.useMemo(
() => [
{
Header: 'Player',
accessor: 'player_name', // accessor is the "key" in the data
},
{
Header: 'Make Cut',
accessor: 'make_cut',
Cell: (props) =>
checkIfValueIsNumberAndRound(props.cell.row.original.make_cut),
},
{
Header: 'Top 20',
accessor: 'top_20',
Cell: (props) =>
checkIfValueIsNumberAndRound(props.cell.row.original.top_20),
},
{
Header: 'Top 10',
accessor: 'top_10',
Cell: (props) =>
checkIfValueIsNumberAndRound(props.cell.row.original.top_20),
},
{
Header: 'Top 5',
accessor: 'top_5',
Cell: (props) =>
checkIfValueIsNumberAndRound(props.cell.row.original.top_20),
},
{
Header: 'Win',
accessor: 'win',
Cell: (props) =>
checkIfValueIsNumberAndRound(props.cell.row.original.top_20),
},
],
[]
);
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
useTable({ columns, data });
return loading ? (
<SpinnerCustom />
) : (
<table {...getTableProps()} style={{ border: 'solid 1px blue' }}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps()}
style={{
borderBottom: 'solid 3px red',
background: 'aliceblue',
color: 'black',
fontWeight: 'bold',
}}
>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
return (
<tr key={i} {...row.getRowProps()}>
{row.cells.map((cell, y) => {
return (
<td
{...cell.getCellProps()}
key={y}
style={{
padding: '10px',
border: 'solid 1px gray',
background: 'papayawhip',
}}
>
{cell.render('Cell')}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
);
}
Figure 2
const data = React.useMemo(() => {
return [...baselineData];
}, [baselineData]);
Figure 3
Figure 4 (ERROR)
this problem may related to initial data for baseLineData.
change the usesState initialize:
const [baselineData, setBaselineData] = useState([]);
I am writing the react-table getting started with typescript, however I am getting an error on the data I am passing into my table function:
utils.js:15 Uncaught TypeError: columns.map is not a function
at linkColumnStructure (utils.js:15:1)
at useTable.js:150:1
at mountMemo (react-dom.development.js:17057:1)
at Object.useMemo (react-dom.development.js:17517:1)
at Object.useMemo (react.development.js:1645:1)
at useTable (useTable.js:149:1)
at Table (App.tsx:9:1)
at renderWithHooks (react-dom.development.js:16141:1)
at mountIndeterminateComponent (react-dom.development.js:20838:1)
at beginWork (react-dom.development.js:22342:1)
Being new to react/typescript pointers much appreciated on my App.tsx below, if I comment out the Table function the page loads, so I am doing something wrong with my types just not sure what.
import React from 'react';
import { useTable } from 'react-table';
import logo from './logo-main.svg';
import './App.css';
function Table(columns: any, data: any) : any
{
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable({ columns, data });
// Render the UI for your table
return (
<table {...getTableProps()} style={{ border: 'solid 1px blue' }}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th
{...column.getHeaderProps()}
style={{
borderBottom: 'solid 3px red',
background: 'aliceblue',
color: 'black',
fontWeight: 'bold',
}}
>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td
{...cell.getCellProps()}
style={{
padding: '10px',
border: 'solid 1px gray',
background: 'papayawhip',
}}
>
{cell.render('Cell')}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
)
}
function App() {
const data = React.useMemo(
() => [
{
col1: 'Hello',
col2: 'World',
},
{
col1: 'react-table',
col2: 'rocks',
},
{
col1: 'whatever',
col2: 'you want',
},
],
[]
)
const columns = React.useMemo(
() => [
{
Header: 'Column 1',
accessor: 'col1', // accessor is the "key" in the data
},
{
Header: 'Column 2',
accessor: 'col2',
},
],
[]
)
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>Edit <code>src/App.tsx</code> and save to reload!!!</p>
<a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">Learn React today </a>
<Table columns={columns} data={data} />
</header>
</div>
);
}
export default App;
You have
<Table columns={columns} data={data} />
so inside Table the columns and data are part of the first argument, the props object.
function Table({ columns, data }: any) : any
But you should really type your identifiers properly - using any completely defeats the purpose of using TypeScript. Proper typing will let you catch these sorts of problems earlier, during compilation.
type Column = { Header: string, accessor: string };
type Data = { col1: string, col2: string };
function Table({
columns,
data,
}: {
columns: Array<Column>,
data: Array<Data>
}) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable({ columns, data });
// etc
(You don't need to note the return type when TypeScript can infer it automatically - omitting an explicit type when TS can infer it is much preferable to setting it to any)
Your Table function should be
function Table({columns: any, data: any}) : any
instead of
function Table(columns: any, data: any) : any
Because you are passing columns and data as props from here
<Table columns={columns} data={data} />
when call the retriveStudentPhoto() function from h1 tag . I can't get the value return .How do I solve this.
Thanks in advance .
{data.map((val, index) => (
<tr>
<td style={{ outline: 'none' }} data-heading="Photo">
<h1{ retriveStudentPhoto(val.email) }</h1> /*call
this function */
</td>
))}
function retriveStudentPhoto (email) {
var photo = ""
axios.get(`/user-info/${email}`)
.then((result)=>{
photo = result.data[0].profile_photo;
}).catch((error)=>error)
return photo ;
}
Since the function is inside the map , there will be call multiple times and the value will be returned each time. I used the useState hook but not getting results as per demand.
please help me more. Thanks in advance.
complete Code :
import React, { useEffect, useState } from 'react';
import { Button, Alert } from 'react-bootstrap';
import $ from 'jquery';
import axios from '../../config/axios';
import '../Attendance_Table/css/App.scss';
import { useAuth } from "../../contexts/AuthContext";
import { Link, useHistory } from 'react-router-dom';
function PeopleList({ match }) {
const course_code = match.params.course_code;
const { currentUser } = useAuth();
const history = useHistory();
const [msg, setMsg] = useState("");
const [course_name, setcourse_name] = useState("");
var breakOn = 'medium'
let tableClass = 'table-container__table';
if (breakOn === 'small') {
tableClass += ' table-container__table--break-sm';
} else if (breakOn === 'medium') {
tableClass += ' table-container__table--break-md';
} else if (breakOn === 'large') {
tableClass += ' table-container__table--break-lg';
}
const headingColumns = ['Photo', 'Student ID', 'Name', 'Email']
const headingColumns2 = ['Photo', 'Name', 'Email']
const [data, setData] = useState([]);
const [studentsPhoto, setStudentsPhoto] = useState([]);
const [techInfo, setTechInfo] = useState([]);
useEffect(() => {
axios.get(`/course/info/${course_code}`).then((result) => {
setcourse_name(result.data[0].course_name)
})
SearchHandle();
}, [])
let SearchHandle = () => {
axios.get(`people/${course_code}`).then((result) => {
setData(result.data)
// teacher info retrieve
axios.get(`user-info/${result.data[0].tecEmail}`)
.then((res) => {
setTechInfo(res.data[0]);
})
//close teacher retrieve
let student_photo = [];
let promises = [];
for (let i = 0; i < result.data.length; i++) {
promises.push(
axios.get(`/user-info/${result.data[i].email}`)
.then((res) => {
student_photo.push(res?.data[0]?.profile_photo)
})
)
}
Promise.all(promises).then(() => {
setStudentsPhoto(student_photo);
})
}).catch((err) => console.log(err))
}
function retriveStudentPhoto(email) {
var photo = "";
axios.get(`/user-info/${email}`)
.then((result) => {
var photo = result.data[0].profile_photo;
}).catch((error) => error)
return photo;
}
return (
<div>
{/* {msg ? ( */}
<div>
<div className="table-container" style={{ backgroundColor: 'white' }}>
<div className="table-container__title">
<h5>People -- {course_name}({course_code})</h5>
</div>
<h5 style={{ padding: '10px', fontFamily: 'roboto' }}>Teacher</h5>
<table style={{ outline: 'none', border: 'none' }} className={tableClass}>
<thead>
<tr>
{headingColumns2.map((col, index) => (
<th data-heading={index} key={index}>{col}</th>
))}
</tr>
</thead>
<tbody>
<tr>
<td style={{ outline: 'none' }} data-heading="Photo">
{techInfo.profile_photo ? (
<img style={{ borderRadius: '150px', height: '40px', width: '40px' }}
src={techInfo.profile_photo} />
) : (
<img style={{ borderRadius: '150px', height: '40px', width: '40px' }}
src="https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/s75-c-fbw=1/photo.jpg" />
)}
</td>
<td data-heading="Student Name">{techInfo.name} </td>
<td data-heading="Student Email"><span style={{ fontSize: '11.5px' }}>{techInfo.email}</span> </td>
</tr>
</tbody>
</table><br />
<br />
{data.length ? (
<table style={{ outline: 'none', border: 'none' }} className={tableClass}>
<thead>
<tr>
{headingColumns.map((col, index) => (
<th data-heading={index} key={index}>{col}</th>
))}
</tr>
</thead>
<tbody>
{data.map((val, index) => (
<tr>
<td style={{ outline: 'none' }} data-heading="Photo">
<h1>{retriveStudentPhoto(val.email)}</h1>
</td>
<td style={{ outline: 'none' }} data-heading="Student ID">{val.student_id}</td>
<td data-heading="Student Name">{val.student_name} </td>
<td data-heading="Student Email"><span style={{ fontSize: '11.5px' }}>{val.email}</span> </td>
</tr>
))}
</tbody>
</table>
) : (
<div>
<Alert className="md-4 w-100" variant="danger">
No Student add to this course yet
</Alert>
</div>
)}
<br />
<div style={{ textAlign: 'center', paddingBottom: '5px' }}>
<Link to={`/attendance-sheet/${course_code}`}><span>Back to {course_code}</span></Link>
</div>
</div>
</div>
{/* ) : ""} */}
</div>
);
}
export default PeopleList;
Render is a pure, synchronous function. If you need to make asynchronous calls then do this in a lifecycle, in this case, a useEffect hook and store the results in state to be rendered.
Iterate over the result.data array and issue the GET request, and when the request resolves issue a functional state update to create a new data array, using the iterated element's index to inject a new photo property.
const SearchHandle = () => {
axios.get(`people/${course_code}`)
.then((result) => {
setData(result.data);
result.data.forEach(async (item, index) => {
try {
const result = await axios.get(`/user-info/${item.email}`);
const photo = result.data[0].profile_photo;
setData(data => data.map(
(el, i) => i === index
? { ...el, photo }
: el)
)
} catch(error) {
// log error, etc...
}
});
...
}
In the render access the new photo property you added above.
{data.map((val, index) => (
<tr key={val.student_name}>
<td style={{ outline: 'none' }} data-heading="Photo">
<h1>{val.photo}</h1>
</td>
<td style={{ outline: 'none' }} data-heading="Student ID">{val.student_id}</td>
<td data-heading="Student Name">{val.student_name} </td>
<td data-heading="Student Email">
<span style={{ fontSize: '11.5px' }}>{val.email}</span>
</td>
</tr>
)
)}
You are trying to use a function with async data in the render, so probably you dont have the data yet.
Try to keep the data from that axios.get in the state, youd probably want also to implement useEffect to make the call and store it to the state when component mounts
I have the following code working properly except when I click on the following button inside projectSpacedGrid function, I get errors in the browser's console as shown below the code:
<Button
label="Associate Project Spaces"
icon="pi pi-plus"
style={{ marginRight: ".25em", marginTop: ".25em" }}
onClick={e =>
this.setState({
assocAssetsVisible: true
})
}
/>
Here's my full code( I've removed lot of code to keep it as small as possible):
import React from "react";
import * as ReactDOM from "react-dom";
import JqxTabs from "jqwidgets-scripts/jqwidgets-react-tsx/jqxtabs";
import JqxGrid, {
IGridProps,
jqx
} from "jqwidgets-scripts/jqwidgets-react-tsx/jqxgrid";
import JqxButton from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxbuttons';
import JqxInput from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxinput';
import JqxDateTimeInput from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxdatetimeinput';
import JqxWindow from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow';
import JqxDropDownList, { IDropDownListProps } from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxdropdownlist';
import JqxNotification from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxnotification';
import { Button } from "primereact/button";
import { Growl } from "primereact/growl";
import { properties } from ".././properties";
import { Messages } from "primereact/messages";
import axios from "axios/index";
type Props = {
project,
username
};
export interface AssetsState extends IGridProps {
//export interface AssetsState extends IDropDownListProps {
visible: boolean,
assocAssetsVisible: boolean,
project: {},
selectedAsset: [],
addEditLabel: {},
selectedRowIndex: number,
deleteDialogVisible: boolean,
dropdownlistSource:IDropDownListProps["source"];
rendertoolbar: (toolbar: any) => void;
}
export class Assets extends React.PureComponent<Props, AssetsState> {
private growl = React.createRef<Growl>();
//Created Refs for a particular div
private projectSpacesGridElement = React.createRef<HTMLDivElement>();
//Created Refs for the desired widgets (JQXGrid and JQXTabs)
private assetsDataGrid = React.createRef<JqxGrid>();
private myTabs = React.createRef<JqxTabs>();
//Created Refs for editing popups for project spaces tab
private assetsEditWindow = React.createRef<JqxWindow>();
private assetsAddWindow = React.createRef<JqxWindow>();
private id = React.createRef<JqxInput>();
private assetsTypeId = React.createRef<JqxInput>();
private assetCategoryId = React.createRef<JqxInput>();
private locationTypeId = React.createRef<JqxInput>();
private statusIndicatorId = React.createRef<JqxInput>();
private uri = React.createRef<JqxInput>();
private fileName = React.createRef<JqxInput>();
private fileAddCDSName = React.createRef<JqxInput>();
private fileVersion = React.createRef<JqxInput>();
private fileEncodingId = React.createRef<JqxInput>();
private ownerId = React.createRef<JqxInput>();
private createdDate = React.createRef<JqxDateTimeInput>();
private updatedDate = React.createRef<JqxDateTimeInput>();
private createdBy = React.createRef<JqxInput>();
private assetDescription = React.createRef<JqxInput>();
private assetCDSDescription = React.createRef<JqxInput>();
private msgNotification = React.createRef<JqxNotification>();
private firstTabButtonContent = "Add New Project Space ";
private editrow: number = -1;
private baseUrl = properties.baseUrlWs;
private messages = React.createRef<Messages>();
constructor(props: Props) {
super(props);
this.saveEditCDSBtn = this.saveEditCDSBtn.bind(this);
this.cancelEditCDSBtn = this.cancelEditCDSBtn.bind(this);
this.savenewCDSpaceBtn = this.savenewCDSpaceBtn.bind(this);
this.cancelnewCDSpaceBtn = this.cancelnewCDSpaceBtn.bind(this);
const rendertoolbar = (toolbar: any): void => {
const addPSRowClick = () => {
this.assetsAddWindow.current!.open();
};
ReactDOM.render(
<div style={{ margin: '5px' }}>
<div id="button1" style={{ float: 'left' }}>
<JqxButton theme={'material'} onClick={addPSRowClick} width={155} value={'Add Project Space'} />
</div>
</div>,
toolbar[0]
);
};
this.state = {
visible: false,
project: {},
assocAssetsVisible: false,
selectedAsset: [],
addEditLabel: {},
selectedRowIndex: null,
deleteDialogVisible: false,
rendergridrows: (params: any): any[] => {
const data = params.data;
return data;
},
rendertoolbar,
dropdownlistSource:[
{value:0, label:'Individual'},
{value:1, label:'Project'},
{value:2, label:'Institution'},
{value:3, label:'Public'}
]
};
}
public render() {
console.log(this.state.selectedAsset);
return (
<div>
<JqxTabs
ref={this.myTabs}
theme={"arctic"}
width="1390px"
//height={560}
//height={100}
initTabContent={this.initWidgets}
onSelected={this.onTabSelected}
>
<ul>
<li style={{ marginLeft: 30 }}>
<div style={{ height: 20, marginTop: 5 }}>
<div style={{ float: "left" }}></div>
<div
style={{
marginLeft: 4,
verticalAlign: "middle",
textAlign: "center",
float: "left"
}}
>
Project Spaces
</div>
</div>
</li>
</ul>
<div style={{ overflow: "hidden" }}>
<div id="jqxGrid" ref={this.projectSpacesGridElement} />
<div style={{ marginTop: 10, height: "15%", width: "100%" }}></div>
</div>
</JqxTabs>
<JqxWindow ref={this.assetsEditWindow} width={250} height={230} resizable={false}
isModal={false} autoOpen={false} modalOpacity={'0.01'} position={{ x: 68, y: 368 }}>
<div>Edit</div>
<div style={{ overflow: 'hidden' }}>
<table>
<tbody>
<tr>
<td align={'right'}>Name :</td>
<td align={'left'}>
<JqxInput ref={this.fileName} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'}>Version:</td>
<td align={'left'}>
<JqxInput ref={this.fileVersion} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'}>Description:</td>
<td align={'left'}>
<JqxInput ref={this.assetDescription} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'}>Visibility Indicator:</td>
<td align={'left'}>
{/* <JqxInput ref={this.visibilityIndicatorID} width={150} height={23} /> */}
<JqxDropDownList width={100} height={20} source={this.state.dropdownlistSource} selectedIndex={0} autoDropDownHeight={true}/>
</td>
</tr>
<tr hidden>
<td align={'right'}>ID:</td>
<td align={'left'}>
<JqxInput ref={this.id} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Location Type ID:</td>
<td align={'left'}>
<JqxInput ref={this.locationTypeId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Asset Category ID:</td>
<td align={'left'}>
<JqxInput ref={this.assetCategoryId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Asset Type ID:</td>
<td align={'left'}>
<JqxInput ref={this.assetsTypeId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Status Indicator ID:</td>
<td align={'left'}>
<JqxInput ref={this.statusIndicatorId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>URI:</td>
<td align={'left'}>
<JqxInput ref={this.uri} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>File Encoding ID:</td>
<td align={'left'}>
<JqxInput ref={this.fileEncodingId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Owner ID:</td>
<td align={'left'}>
<JqxInput ref={this.ownerId} width={150} height={23} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Created Date:</td>
<td align={'left'}>
<JqxDateTimeInput ref={this.createdDate}
width={150} height={23} formatString={'F'} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Updated Date:</td>
<td align={'left'}>
<JqxDateTimeInput ref={this.updatedDate}
width={150} height={23} formatString={'F'} />
</td>
</tr>
<tr hidden>
<td align={'right'}>Created By:</td>
<td align={'left'}>
<JqxInput ref={this.createdBy} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'} />
<td style={{ paddingTop: '10px' }} align={'right'}>
<JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.saveEditCDSBtn} width={50}>
Save
</JqxButton>
<JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.cancelEditCDSBtn} width={50}>
Cancel
</JqxButton>
</td>
</tr>
</tbody>
</table>
</div>
</JqxWindow>
<JqxWindow ref={this.assetsAddWindow} width={250} height={230} resizable={false}
isModal={false} autoOpen={false} modalOpacity={'0.01'} position={{ x: 68, y: 368 }}>
<div>{this.firstTabButtonContent}</div>
<div style={{ overflow: 'hidden' }}>
<table>
<tbody>
<tr>
<td align={'right'}>Name:</td>
<td align={'left'}>
<JqxInput ref={this.fileAddCDSName} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'}>Description:</td>
<td align={'left'}>
<JqxInput ref={this.assetCDSDescription} width={150} height={23} />
</td>
</tr>
<tr>
<td align={'right'}>Visibility Indicator:</td>
<td align={'left'}>
<JqxDropDownList width={100} height={20} source={this.state.dropdownlistSource} selectedIndex={0} autoDropDownHeight={true} />
</td>
</tr>
<tr>
<td align={'right'} />
<td style={{ paddingTop: '10px' }} align={'right'}>
<JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.savenewCDSpaceBtn} width={50}>
Save
</JqxButton>
<JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.cancelnewCDSpaceBtn} width={50}>
Cancel
</JqxButton>
</td>
</tr>
</tbody>
</table>
</div>
</JqxWindow>
<JqxNotification ref={this.msgNotification}
width={250} position={'top-left'} opacity={0.9} autoOpen={false}
autoClose={true} animationOpenDelay={800} autoCloseDelay={3000} template={'info'} appendContainer={'#forNotification'}>
<div>
Record Deleted Successfully!
</div>
</JqxNotification>
</div>
);
}
//Tab 1
private projectSpacesGrid = () => {
const source: any = {
datafields: [
{ name: "id", type: "long" },
{ name: "assetsTypeId", type: "long" },
{ name: "fileName", type: "string" },
{ name: "locationTypeId", type: "long" },
{ name: "uri", type: "string" },
{ name: "fileVersion", type: "string" },
{ name: "fileEncodingId", type: "long" },
{ name: "ownerId", type: "long" },
{ name: "createdDate", type: "date",format: "dd-MMM-yy" },
{ name: "assetCategoryId", type: "long" },
{ name: "assetDescription", type: "string" },
{ name: "createdBy", type: "string" },
{ name: "updatedDate", type: "date",format: "dd-MMM-yy" },
{ name: "statusIndicatorId", type: "long" },
{ name: "visibilityIndicatorId", type: "long" },
{ name: "displayedValues", type: "string" }
],
deleterow: (rowid: number,commit:any): void => {
console.log("Delete row method called in source of Project Spaces");
console.log("Role ID:" + rowid);
commit(true);
},
datatype: "json",
root: "assets",
url: this.baseUrl + `api/assets/search/getAssetsByProjectId`
};
const dataAdapter = new jqx.dataAdapter(source, {
//async: false,
autoBind: true,
downloadComplete: (data: any, status: any, xhr: any): void => {
source.totalrecords = parseInt(data["page"].totalElements);
console.log("Total Assets Records check"+source.totalrecords);
},
formatData: (data: any): any => {
data.value = this.props.project.id;
data.page = data.pagenum;
data.size = data.pagesize;
if (data.sortdatafield && data.sortorder) {
data.sort = data.sortdatafield + "," + data.sortorder;
}
return data;
},
loadError: (xhr: any, status: any, error: any) => {
alert('Error loading "' + source.url + '" : ' + error);
}
});
const columns: IGridProps["columns"] = [
{ datafield: "id", text: "ID Number", width: 100,hidden:true },
{ datafield: "assetsTypeId", text: "Assets Type ID", width: 100, hidden: true },
{ datafield: "fileName", text: "Name", width: 275 },
{ datafield: "fileVersion", text: "File Version", width: 275, hidden: true },
{ datafield: "fileEncodingId", text: "File Encoding", width: 275, hidden: true },
{ datafield: "ownerid", text: "Owner ID", width: 100, hidden: true },
{ datafield: "assetCategoryId", text: "Asset Category ID", width: 100, hidden: true },
{ datafield: "statusIndicatorId", text: "Status Indicator ID", width: 100, hidden: true },
{ datafield: "visibilityIndicatorId", text: "Visibility Indicator ID", width: 100, hidden: true },
{ datafield: "displayedValues", text: "Display Values", width: 100, hidden: true },
{
datafield: "assetDescription",
text: "Description",
width: 250
},
{ datafield: "locationTypeId", text: "Location Type", width: 150 },
{ datafield: "uri", text: "URI", width: 150 },
{ datafield: "ownerId", text: "Owner", width: 150 },
{
//cellsformat: "d",
cellsformat: "MM/dd/yyyy",
datafield: "createdDate",
text: "Created Date",
width: 150
},
{
//cellsformat: "d",
cellsformat: "MM/dd/yyyy",
datafield: "updatedDate",
text: "Updated Date",
width: 100
},
{
text: "Delete ",
buttonclick: (): void => {
},
cellsrenderer: (): string => {
return "Delete";
},
columntype: "button",
datafield: "Delete",
width: 80
},
{
text: "Edit Asset",
buttonclick: (row: number): void => {
// show the popup window.
this.assetsEditWindow.current!.open();
},
cellsrenderer: (): string => {
return "Edit";
},
columntype: "button",
datafield: "Edit",
width: 80
}
];
const grid =
this.state.visible || this.state.assocAssetsVisible ? null : (
<div>
<JqxGrid
ref={this.assetsDataGrid}
width={"100%"}
height={"100%"}
theme={"arctic"}
source={dataAdapter}
columns={columns}
showtoolbar={true}
pageable={true}
pagesize={50}
scrollmode={"default"}
rendertoolbar={this.state.rendertoolbar}
sortable={true}
/>
<Button
label="Associate Project Spaces"
icon="pi pi-plus"
style={{ marginRight: ".25em", marginTop: ".25em" }}
onClick={e =>
this.setState({
assocAssetsVisible: true
})
}
/>
</div>
);
ReactDOM.render(grid, this.projectSpacesGridElement.current!);
};
private saveEditCDSBtn(): void {
if (this.editrow >= 0) {
this.assetsEditWindow.current!.hide();
}
}
private cancelEditCDSBtn(): void {
this.assetsEditWindow.current!.hide();
}
private savenewCDSpaceBtn(): void {
this.assetsAddWindow.current!.hide();
}
private cancelnewCDSpaceBtn(): void {
this.assetsAddWindow.current!.hide();
}
private initWidgets = (tab: any) => {
switch (tab) {
case 0:
this.projectSpacesGrid();
break;
}
};
private onTabSelected = (event: any) => {
if (event.args) {
let tabIndex = event.args.item;
switch (event.args.item) {
case 0:
this.assetsAddWindow.current!.setTitle(this.firstTabButtonContent);
break;
}
}
};
}
Error Below:
The above error occurred in the <JqxWindow> component:
in JqxWindow (created by Assets)
in div (created by Assets)
in Assets (created by ProjectTabView)
in div (created by TabView)
in div (created by TabView)
in div (created by TabView)
in TabView (created by ProjectTabView)
in ProjectTabView (created by ProjectView)
in div (created by ProjectView)
in ProjectView (created by Route)
in Route (created by Main)
in Switch (created by Main)
in div (created by Main)
in div (created by Main)
in Router (created by BrowserRouter)
in BrowserRouter (created by Main)
in Main
in ErrorBoundary
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
TypeError: "h is undefined"
propertyChangedHandler webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxwindow.js?:8
setvalueraiseevent webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
set webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
set webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
jqxWidgetProxy webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
b.jqx.jqxWidget/b.fn[h]/< webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
h webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
setOptions webpack:///./node_modules/jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow/react_jqxwindow.esm.js?:88
componentDidUpdate webpack:///./node_modules/jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow/react_jqxwindow.esm.js?:82
React 6
unstable_runWithPriority webpack:///./node_modules/scheduler/cjs/scheduler.development.js?:818
React 5
unstable_runWithPriority webpack:///./node_modules/scheduler/cjs/scheduler.development.js?:818
React 6
Adding screenshots of complete error from the browser console:
Is it something related to associateAssetsVisible:true variable that I'm using?