Cannot read properties of undefined (reading 'children') using reactjs - javascript

how I implement custom sort for columns that have render cell field? for example I have multiple data that has status Active and InActive, I want to sort it if the user click the header and i want to display it with design, status active color green and if the status is Inactive the font color is red
export default function App() {
const classes = useStyles();
const header = [
{ field: "id", headerAlign: "left", headerName: "ID", hide: true },
{
field: "username",
headerAlign: "left",
headerName: "Username",
width: 250,
sortable: true
},
{
field: "email",
headerAlign: "left",
headerName: "Email",
width: 230,
sortable: true
},
{
field: "status",
headerName: "Status",
width: 100,
cellClassName: (params) =>
clsx("super-app", {
active: params.formattedValue.trim() === "Active",
inactive: params.formattedValue.trim() !== "Active"
}),
valueFormatter: ({ value }) =>
value.props.children.trim() === "Active"
? `${value.props.children.trim()}`
: "InActive"
}
];
return (
<div className={classes.root}>
<DataGrid rows={rows} columns={header} />
</div>
);
}
example data
const rows = [
{
id: 1,
username: "Silvestr Irma",
email: "SilvestrIrma#gmail.com",
status: "Active"
},
{
id: 2,
username: "Iruma",
email: "Iruma#gmail.com",
status: "Active"
},
{
id: 3,
username: "HeroidiasMetody",
email: "HeroidiasMetody#gmail.com",
status: "InActive"
}
];
current code https://codesandbox.io/embed/mutable-microservice-qi6olw?fontsize=14&hidenavigation=1&theme=dark

Related

How to remove and add columns to a table after a user search?

function Products() {
const [rowData, setRowData] = useState([]);
const [search, setSearch] = useState("");
const columns = [
{ headerName: "Product", field: "product"},
{ headerName: "Name", field: "name" },
{ headerName: "Date", field: "date" },
{ headerName: "Type", field: "type", hide : true },
{ headerName: "Open", field: "open", hide : true },
{ headerName: "High", field: "high", hide : true },
{ headerName: "Percentage", field: "pct", hide : true }
];
useEffect(() => {
fetch('http://localhost:8080/all')
.then(res => { return res.json();
})
.then (data => { setRowData(data);
})
}, []);
useEffect(() => {
fetch(`http://localhost:8080/all?product=${search}`)
.then(res => { return res.json();
})
.then (data => { setRowData(data);
})
}, [search]);
return (
<div className="Products">
<p className="one">Select product</p>
<SearchBar onSubmit={setSearch} />
<div
className="ag-theme-balham"
style={{
height: "300px",
width: "600px"
}}
>
<AgGridReact
columnDefs={columns}
rowData={rowData}
/>
</div>
</div>
)
function SearchBar(props) {
  const [innerSearch, setInnerSearch] = useState("");
  return (
    <div >
      <input
        aria-labelledby="search-button"
        name="search"
        id="search"
        type="search"
        value={innerSearch}
        onChange={e => setInnerSearch(e.target.value)}
      />
      <button
        id="search-button"
        type="button"
        onClick={() => props.onSubmit(innerSearch)}
      >
        Search
      </button>
    </div>
  );
}
};
I don't know if this is even a way to do it, but in my code I have two APIs, and in one of them I can search based on product only via the search parameter. But as seen in my column headers, by default I only want the first three columns to show in the table which are: "Product, Name, Date". The rest don't exist/are hidden.
But then once the user searches for a product and hits enter, the first three columns "Product, Name, Date" disappear and the next four appear only: "Type, Open, High, Percentage".
Is there any way to do this by somehow erasing/filtering/hiding the columns?
Make set of two columns based on your search then bind that column.
const columns = [
{ headerName: "Product", field: "product"},
{ headerName: "Name", field: "name" },
{ headerName: "Date", field: "date" },
];
Bind another when searching based on the product search.
const columns1 = [
{ headerName: "Type", field: "type", hide : true },
{ headerName: "Open", field: "open", hide : true },
{ headerName: "High", field: "high", hide : true },
{ headerName: "Percentage", field: "pct", hide : true }
];

How to add image object in the table?

Note: Image is in the database named as "profileImage" I want to make image object that is dynamic as like other objects, whenever I add this code
{
label: "Image",
name: "profileImage",
}
it simply display the image endpoint like 3704545668418.PNG
and the url for profileImage is https://cloudclinicdevapi.azurewebsites.net/Profile/3704545668418.PNG
Now please tell me how can I add image column in this table
this.state = {
columns: [
{
label: "National ID",
name: "nationalID",
sortable: true,
filter: true,
options: {
customBodyRender: (val) => (
<NavLink className="NavLink" to={`/EditPatient?Patient=${val}`}>
{val}
</NavLink>
),
},
},
{
label: "Patient Name",
name: "name",
filter: true,
},
{
//want to add Image here
},
{
label: "Phone Number",
name: "phone",
sortable: true,
filter: true,
},
{
label: "Address",
name: "address",
sortable: true,
filter: true,
},
{
label: "ID",
hide: true,
name: "nationalID",
button: {
show: true,
value: "Make an Appointments",
operation: (val) => this.needAppointment(val),
},
},
],
rowSelection: "single",
rowData: [],
}`
Looks like you are using mui-datatables. If so, you should be able to just use another custom renderer:
{
// add Image
label: "Image",
name: "profileImage",
sortable: false,
filter: false,
options: {
customBodyRender: (val) => (
<img src={`https://cloudclinicdevapi.azurewebsites.net/Profile/${val}`} />
),
},
},

Set width property array dynamically

I have a react table with group fields and resize-able columns.The columns are like below:
export const columns = [
{ title: 'Year Week',
dataIndex: 'year_week',
editable: false,
width: 60,
},
{
title: 'Actual Bank Amount',
dataIndex: 'actual_bank_amount',
width: 60,
editable: true
},
{
title: 'External Incomings',
key: 'external_incomings',
dataIndex: 'external_incomings',
className: "ext-in",
editable: true,
children: [
{ title: 'Rental Income/Leasing Income', width: 60, dataIndex: "ext_in_rental_income", key: "ext_in_rental_income", editable: true },
{ title: "Tax Refund", width: 60, dataIndex: "ext_in_tax_refund", key: "ext_in_tax_refund", editable: true },
{ title: "Dividends Income", width: 60, dataIndex: "ext_in_dividends_income", key: "ext_in_dividends_income", editable: true },
{ title: "Licence Income", width: 60, dataIndex: "ext_in_licence_income", key: "ext_in_licence_income", editable: true },
{ title: "Other Income", width: 60, dataIndex: "ext_in_other_income", key: "ext_in_other_income", editable: true },
]
}]
I am resizing the width in my reducer as below, but I am sure, we can do it in a far better way. Can someone please suggest a better way to do this. Below is my reducer code.
I simple words I want to set the width property dynamically in a function, where I have access to the dynamic "width" and the "dataIndex".
case 'SET_COLUMN_WIDTH':
const newColmuns = state.columns
Object.keys(newColmuns).map((key) => {
if (newColmuns[key].children) {
let Datakey = newColmuns[key].children.findIndex(item => item.dataIndex === action.payload.dataIndex)
if (Datakey > 0) {
newColmuns[key].children[Datakey].width = action.payload.size.width;
return
}
}
})
return {
...state,
columns: newColmuns
}
for(var col of columns)
{
if(col.children)
{
for(var child of col.children)
{
child.width = 123;
}
}
}

Grab row data onclick of a field in material-table

import MaterialTable from "material-table";
import ShipmentContext from "../context/ShipmentContext";
const ItemsTable: React.FC = () => {
const shipmentcontext = useContext(ShipmentContext);
const { filtered } = shipmentcontext.State;
return (
<>
<div style={{ width: "100%", overflowY: "hidden" }}>
<MaterialTable
options={{
search: false,
showTitle: false,
toolbar: false,
paging: false,
padding: "dense",
maxBodyHeight: "400px",
minBodyHeight:"400px",
paginationType: "stepped",
tableLayout: "fixed"
}}
columns={[
{ title: "AWB NUMBER", field: "awbno" ,},
{ title: "TRANSPORTER", field: "carrier" },
{ title: "SOURCE", field: "from" },
{ title: "DESTINATION", field: "to" },
{ title: "BRAND", field: "carrier" },
{ title: "START DATE", field: "pickup_date" },
{ title: "ETD", field: "" },
{
title: "STATUS",
field: "current_status",
cellStyle: {
color: "green",
},
},
]}
data={filtered}
/>
</div>
</>
);
};
export default ItemsTable;
I want to gather the data of the field i clicked on the row.As here the data is dynamic i am unable to make an onClick method to grab the object which is clicked in the row.
My table look like this :
table
I want an onClick method which when i click on any AWB number grabs the data of it
You can use the custom render function for that to add a custom onClick handler like this:
columns={[
{ title: "AWB NUMBER", field: "awbno" , render: row => <div onClick={() => console.log(row.awbno)}>{row.awbno}</div>}, // This will be called if this cell is clicked
{ title: "TRANSPORTER", field: "carrier" },
{ title: "SOURCE", field: "from" },
{ title: "DESTINATION", field: "to" },
{ title: "BRAND", field: "carrier" },
{ title: "START DATE", field: "pickup_date" },
{ title: "ETD", field: "" },
{
title: "STATUS",
field: "current_status",
cellStyle: {
color: "green",
},
},
]}
```

Can't get React Grid Ag-grid to automatically resize itself at screen width

So just like the title says I am having trouble resizing the columns on my grid to fit smaller screens. I've been trying to use this.gridApi.sizeColumnsToFit(), however it doesn't seem to be doing anything. I also want to reduce the number of columns on the screen to four, which I am able to do if i do not call this.gridApi.sizeColumnsToFit(). The moment I do call sizeColumnsToFit it populates all the columns. (also tried to resize then hide the columns)
import React, { Component, Fragment } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-theme-bootstrap.min.css'
import '../Review/ag-grid.css';
import { AuthorizeService } from '../api-authorization/AuthorizeService';
import { AllCommunityModules } from "#ag-grid-community/all-modules";
import "#ag-grid-community/all-modules/dist/styles/ag-grid.css";
import "#ag-grid-community/all-modules/dist/styles/ag-theme-balham.css";
import ImageRenderer from '../UI/imageRenderer';
import CharacteristicRenderer from '../UI/characteristicRenderer';
import ShippingRenderer from '../UI/shippingRenderer';
import { fetchAssets } from '../../utils/fetchAsset';
export class Approve extends Component {
constructor() {
super();
this.state = {
ColumnDefs: [
{ headerName: "Inventory Tag Number", field: "inventoryTagNumber", sortable: true, filter: true },
{ headerName: "Locations", field: "location.locationName", sortable: true, filter: true },
{ headerName: "Sequence", field: "transaction.sequence", sortable: true, filter: true },
{ headerName: "Item #", field: "transaction.item", sortable: true, filter: true },
{ headerName: "Quantity", field: "quantity", sortable: true, filter: true },
{ headerName: "Make", field: "make", sortable: true, filter: true },
{ headerName: "Model", field: "model", sortable: true, filter: true },
{ headerName: "Serial #", field: "serialNumber", sortable: true, filter: true },
{ headerName: "Category", field: "category", sortable: true, filter: true },
{ headerName: "SubCategory", field: "subCategory", sortable: true, filter: true },
{ headerName: "Description", field: "description", sortable: true, filter: true },
{ headerName: "Characteristics", field: "characteristics", cellRenderer: "characteristicRenderer" },
{ headerName: "Images", field: "images", cellRenderer: "imageRenderer" },
{ headerName: "Condition", field: "condition", sortable: true, filter: true },
{ headerName: "Shipping Info", field: "shipping", cellRenderer: "shippingRenderer" },
{ headerName: "Notes", field: "notes" },
],
frameworkComponents: {
imageRenderer: ImageRenderer,
characteristicRenderer: CharacteristicRenderer,
shippingRenderer: ShippingRenderer
},
rowDefs: [
// default rows
]
};
this.onGridReady = this.onGridReady.bind(this);
this.onFirstDataRendered = this.onFirstDataRendered.bind(this);
fetchAssets().then(data => {
this.setState({
rowDefs: data
});
}).catch(err => {
console.dir(err);
throw err;
});
}
onGridReady = params => {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
}
mapImages(imgData) {
console.log(imgData);
return imgData;
}
onFirstDataRendered = params => {
// params.api.sizeColumnsToFit();
};
onGridReady(gridOptions) {
gridOptions.api.addGlobalListener(function(type, event) {
if (type.indexOf('column') >= 0) {
console.log('Got column event: ', event);
}
});
var widthWindow = window.innerWidth;
if (widthWindow < 376) {
console.log("its smaller");
gridOptions.columnApi.setColumnsVisible(['transaction.sequence', 'transaction.item','quantity', 'make', 'serialNumber', 'category', 'subCategory', 'characteristics', 'images', 'condition', 'shipping', 'notes'], false);
this.gridApi.sizeColumnsToFit();
}
}
render() {
return (<Fragment>
<h1>Asset Approve</h1>
<div
className="ag-theme-bootstrap"
style={{
height: '90vh',
width: '90vw',
marginTop: '3em'
}}>
<AgGridReact
pagination={true}
columnDefs={this.state.ColumnDefs}
rowData={this.state.rowDefs}
frameworkComponents={this.state.frameworkComponents}
onGridReady={this.onGridReady}
></AgGridReact>
</div>
</Fragment>);
}
}
So How can we both have the columns resized to fit, and hide the other columns?
OK, this is what worked for me
<AgGridReact
rowData={data}
columnDefs={columns}
// this is where the magic happens
onGridColumnsChanged={() => columnApi && columnApi.autoSizeAllColumns()}
onGridReady={params =>setColumnApi(params.columnApi)}
/>
so basically I will resize all the columns if any column changed, if you need it there is also a onCellValueChanged event that you can pass a function where you can resize it.
I know it's a bit late to reply, but hey!!! maybe another developer friend may need assistance too.

Categories

Resources