How to hide a certain column of a table using antd? - reactjs

Sample code below
{
title: 'Site',
dataIndex: 'site'
}
I want to hide the site column and im still new to the antd react ui.
And theres no show/hide function in column API of antd docs.
I want to hide it after a certain condition has been met like there are 2 user types. Admin user and General user.
if(user_role = admin_user){
show column
elseif(user_role = general_user){
hide column
}

getColumns = (userRole) => {
switch(userRole){
case 'AdminUser': { return //return admin user columns here }
case 'GeneralUser': { return //return the genral user columns here }
default: { return //handle other cases.. or raise error}
}
}
In your table component call the function.(Assuming your state has the user role)
<Table columns = {this.getColumns(this.state.userRole)} />

Related

How to keep the check box checked , when navigating to other page of react pagination

I want to ask , how to keep save the id's of the check boxes in a state , and whenever i switched back to first page it automatically search the element with id and mark check boxes automatically.
and if i unmark the checkbox , it deletes the id from the state.
i am able to think about the logic , but cant able to code,it
Small help ,will leads to solve this problem
While switching to other pages, i am succesfully saving the data ,by updating the state
`
// push all the unique objects (combination of previous state of selectedPayments and data from list)
setSelectedPayments((prevState) => {
var arr = [...prevState, ...list];
var newState = [
...new Map(arr.map((item) => [item.id, item])).values(),
];
return newState;
});
console.log('Selected payments are', selectedPayments);
`
Also , removing the objects , if again the checkbox is unchecked ,and updating the state
`
// pull all the objects , which got unChecked
setSelectedPayments((prevState) => {
var newState = prevState.filter(function (objFromA) {
return !list.find(function (objFromB) {
return objFromA.id === objFromB.id;
});
});
return newState;
});
`
Only facing issue with keeping track of the checked boxes, i have implimented this, this is keeping track of main(parent checkbox).
How to extract the ids saved and check the checkboxes when we naviagete from one page to another
`
let elementId = e.target.id;
if (selectedBoxes.includes(elementId)) {
const newArray = selectedBoxes.filter((e) => e !== elementId);
setSelectedBoxes(newArray);
} else {
setSelectedBoxes((prevState) => {
return [...prevState, elementId];
});
}
`
First i modified the Res Json , so that it set's a property isSelected = true,
by comparing the element from the selectedPayments
inAll check handler , i set the selectedPayments like this
And render using this
This is how ,i solved this problem.
** Better and improved answers are always welcome, please share your views.

ag-grid react exportMultipleSheetsAsExcel with coulmnKeys

I'm novice in ag-grid react. Currently I want to export the grid data as excel with multiple sheets. The requirement is, export only selected columns(User will be prompted to choose columns to be present in the excel on click of Export button). I know, we should be using columnKeys attribute. But something, I'm missing here. After clicking columns , I'm getting this error when I click export option
AG Grid: Invalid params supplied to getMultipleSheetsAsExcel() - ExcelExportParams.data is empty.
getRefsFromParent(childRefs) {
this.setState({
myRequestedRefs: childRefs
});
/* Export multiple sheets commence here */
var spreadsheets = []; // var for storing multiple sheets data
for (let i = 0; i < this.state.checkedSheets.length; i++) {
if (this.state.checkedSheets[i] == 'Engagements') {
spreadsheets.push(
//Referring Engagement Reference passed from Parent Component
this.state.engRef.current.api.getSheetDataForExcel({
sheetName: 'Engagements'
})
)
}
else {
spreadsheets.push(
//Sheets will be created based on the selected items from the sheetsList
this.state.ref.current.api.getSheetDataForExcel({
onlySelected: false,
sheetName: this.state.checkedSheets[i]
})
)
}
console.log("Spreadsheets ", spreadsheets);
}
this.state.ref.current.api.exportMultipleSheetsAsExcel({
data: spreadsheets,
columnKeys: this.state.pickedColumns, //columns selected in the modal by user
fileName: 'client-details.xlsx',
});
}

React (Reakit): How to ask for confirmation, when toggling a checkbox?

I'm wondering, if there's a way to ask for confirmation with Reakit's checkbox. I'm using Reakit, since I found a quick way to get it to read database's boolean information, but I welcome other methods too!
I'm used to doing confirmations with buttons with async and window.confirm:
<button onClick={async hiStackOverflow => {
if (window.confirm("Want to do this?")) {
// saving to database here
}
}}>
But I didn't figure out how to do it with a checkbox. In short, I want for the page to confirm (and then save to database), when the user toggles on/off the checkbox.
// personData = database table, with boolean "recurring"
// row = which entity in a table we are talking about
function CheckboxThing ({ row, personData }) {
const checkbox = useCheckboxState({state: personData[row].recurring});
return (
<div className="checkbox-admin-other">
<Checkbox
{...checkbox}
// what here?? onClick or something?
/>
</div>
);
}
Reakit's checkbox can be used like this:
const toggle = () => setChecked(!checked);
return <Checkbox checked={checked} onChange={toggle} />;
This means that the checkbox will be checked if the variable 'checked', which needs to be put in the state of your React component, is true and that the method called 'toggle' will be called when the user toggles the checkbox. In that method, you can put the code which will show the Confirmation Prompt and then change checked if user clicked 'Yes' or leave it as it is if they check 'No'.
You can "observe" changes on checkbox.state using React Hooks:
function CheckboxThing({ row, personData }) {
const checkbox = useCheckboxState({ state: personData[row].recurring });
React.useEffect(() => {
// checking if state has changed
if (checkbox.state !== personData[row].recurring) {
if (window.confirm("Want to do this?")) {
// saving to database here
} else {
// revert checkbox state otherwise
checkbox.setState(!checkbox.state);
}
}
}, [checkbox.state, checkbox.setState, personData[row].recurring]);
return (
<div className="checkbox-admin-other">
<Checkbox {...checkbox} />
</div>
);
}
With React.useEffect, the user will see the checkbox checked before window.confirm opens. But you can use React.useLayoutEffect instead if you want it to open before checkbox state changes on the UI.
After coding around a little while, I found the solution! It turns out, you can put async inside Reakit Checkbox. Thanks to Tomislav and Diego, their answers helped me try different things and get it clean!
Here's the full function:
// admin can edit the right to join back to the queue after getting to the front
function RecurringBox ({ row, personData }) {
// sets the original values
const checkbox = useCheckboxState({state: personData[row - 1].recurring});
return (
<Checkbox {...checkbox} onChange={async checkboxSwitch => {
if (window.confirm("Change it?")) {
checkboxSwitch.persist();
// saving it to the database
await put(`${process.env.API_PATH}/person`,
{
"id": personData[row - 1].id,
"name": personData[row - 1].name,
"recurring": checkboxSwitch.target.checked
});
reload(`${process.env.API_PATH}/person`);
} else {
return null;
}
}}/>
);
}

Wix Corvid Database Filtering Conditional

I have setup a filter using the code queen video-works great except one part-
I got two dropdowns,
Category and subcategory,I am trying to setup simple conditional filtering
When I click category, on change event happens -> subcategory gets activated(this is working)
Subcategory should conditionally filter and show only relevant/matching results,however shows all the results from the field.
For eg. Category dropdown we choose - industrial houses -> Subcategory becomes active and shows only the results that match for the industrial category
Currently shows every element from the field,can anyone help me?
Here is the code.Thank you
$w.onReady(function () { //code that clears the search
$w('#clear').onClick(() => {
$w('#dropdown1 , #dropdown2 , #dropdown3, #dropdown4, #dropdown5 , #dropdown6').value = "";
$w('#dataset1').setFilter(wixData.filter())
.then();
});
});
export function button1_click(event, $w) { //filter on click even
let searchValue = $w("#locationSearch").value;
$w("#dataset1").setFilter(wixData.filter()
.contains("bathrooms",$w('#dropdown1').value)
.contains("bedrooms", $w('#dropdown2').value)
.contains("typesOfProperties", $w('#dropdown5').value) //CATEGORY DROPDOWN
.eq("subcategory", $w("#dropdown6").value) //SUBCATEGORY DROPDOWN
.contains('propertyAddress', searchValue)
.contains('averagePrice', $w('#dropdown7').value))
.then((results) => {
console.log("Dataset is now Filtered");
$w("#repeater1").data = results.items;
})
.catch((err) => {
console.log(err);
});
$w("#repeater1").expand();}
//FILTER FROM THE CODE QUEEN VIDEO THAT SHOULD SHOW ONLY MATCHING RESULTS
export function dropdown5_change(event, $w) {
SubCatFilter(); }
function SubCatFilter (){
$w("#dropdown6").enable(); //SUBCATEGORY DROPDOWN
$w("#dataset1").setFilter(wixData.filter() //BOTH FIELDS IN THE SAME DATASET
.eq("subcategory", $w("#dropdown5").value) //SUBCATEGORY KEY FIELD
)
}

Create tree in angular-grid (ag-grid) with async data loading

I am trying to use angular-grid (ag-grid) to display a tree like in the example provided in the documentation:
http://www.angulargrid.com/example-file-browser/index.php
In the given example, all the data is already provided. How do I use async data loading when a row group is expanded? My guess is that i need to write my own group row renderer.
I came recently to the same problem in my React.js app and found solution. It's similar to what #leden posted but I found solution how to maintain current row expansions between table rows update.
The solution is as follow:
Add dummy child row for each top-level row. Can be empty or can have loading... string for example in first column.
On event getNodeChildDetails, which is called each time you update your table rowData, you can specify if a row should be expanded or not. So the idea is that we keep track of what is expanded and what is not.
getNodeChildDetails = (rowItem) => {
if (rowItem.children) {
return {
group: true,
expanded: rowItem.id in this.expandedRows,
children: rowItem.children,
};
}
else {
return null;
}
};
On event rowGroupOpened we keep track which rows are expanded.
rowGroupOpened = (param) => {
const id= param.node.data.id;
if(!param.node.expanded) {
delete this.expandedRows[id];
return;
}
this.expandedRows[id] = true;
if (param.node.data.children.length !== 1) { // Here we need to check if only dummy row is present
return;
}
this.api.showLoadingOverlay();
// Here I simulate fetching data from server
setTimeout(() => {
this.rowData.forEach((e) => {
if (e.id == id) {
e.children = [
// Add fetch rows
]
}
});
this.api.setRowData(this.rowData); // Setting data, will trigger getNodeChildDetails call on each row
this.api.hideOverlay();
}, 1000);
};
The grid doesn't support lazy loading of the tree data out of the box. So yes you would have to write your own cellRenderer to achieve this.
PS I'm the author of ag-Grid, so you can take this answer as Gospel!
Just an idea, but I think that you could add a single placeholder child row to the group with "loading..." in the first cell, with the group's onRowGroupOpened event set to make the ajax call to get the data from the server, with the onreadystatechange then adding the new rows and replacing the placeholder one. The initial placeholder row can contain server-calculated total values to drive aggregation (total) values in the group row's cells, which would remain the same when real data replaces the placeholder.
I have come up with a basic test of the approach. It's not perfect, as the grid rebuilds after each expansion (I can't find an elegant way to just append the new rows), but it does work.
At the very top of the script is the AJAX call for detail. Although this happens later in the flow I put it at the top, so that if the server receives this request, it provides data and exits, without loading the page again. Alternatively you could just put it into another file.
<?php
if (isset($_REQUEST['g'])) { // this is the AJAX request for child data (called later, but needed at the start of the script)
// get connection to database
require_once 'db_connection.php'; $dbh=getConnection();
// query data to array
$sql="SELECT accounts.description AS account, '' AS info,
tx.amnt AS amount, 1 AS transactions
FROM tx
INNER JOIN accounts ON tx.account=accounts.account_id
WHERE accounts.description='".$_REQUEST['g']."'";
$data=array();
$result = $dbh->query($sql);
while ($row = $result->fetch_assoc()) {
$data[]=$row;
}
$result->free();
// return data as JSON
print json_encode($data, JSON_NUMERIC_CHECK);
exit;
}
?>
Then immediately after that comes a normal HTML page with a little bit more php within the javascript in the head:
<!DOCTYPE html>
<html>
<head>
<script src="lib/ag-grid-enterprise-master/dist/ag-grid-enterprise.js"></script>
<script>
// get JSON for initial group-level data from server with a little snippet of php which is called when the page is first loaded
var rowData =
<?php
// get connection to the database
require_once 'db_connection.php'; $dbh=getConnection();
// query data to array
$sql = "SELECT description AS account, 'loading...' AS info,
SUM(tx.amnt) AS amount, COUNT(tx.tx_id) AS transactions
FROM accounts
INNER JOIN tx ON accounts.account_id=tx.account
GROUP BY accounts.account_id";
$data=array();
$result = $dbh->query($sql);
while ($row = $result->fetch_assoc()) {
$data[]=$row;
}
$result->free();
// inject the JSON into the javascript assignment to rowData
print json_encode($data, JSON_NUMERIC_CHECK);
?>;
// (back in javascript again)
// event function for when a group is expanded
function getChildRows(data) {
if (data.node.allLeafChildren) {
if (data.node.allLeafChildren.length > 0) {
if (data.node.allLeafChildren[0].data.info==="loading...") {
// data for this group has not yet been loaded, so make AJAX request for it
var xmlHttp=new XMLHttpRequest();
xmlHttp.onreadystatechange=function() {
if ((xmlHttp.readyState===4) && (xmlHttp.status === 200)) {
// call function to add the new rows to the grid
addRecords(JSON.parse(xmlHttp.responseText));
}
};
var requestParameters="g="+encodeURIComponent(data.node.key);
xmlHttp.open("POST", "index.php", true); // call to this same script
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.send(requestParameters);
}
}
}
}
function addRecords(data) {
var x; var d=new Array();
var acc=data[0].account;
for(x in gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren) {
if (gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren[x].data.account===acc) {
// this is group we are replacing with new data
for (x in data) {
d.push(data[x]);
}
} else {
// this node is just the data as currently loaded to the grid (no change)
d.push(gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren[x].data);
}
}
gridOptions.api.setRowData(d);
}
// set up the grid (standard stuff)
var columnDefs = [
{headerName: "Account", field: "account", rowGroupIndex: 0, cellRenderer: "group", cellRendererParams : {suppressCount: true} },
{headerName: "Info", field: "info"},
{headerName: "Amount", field: "amount", aggFunc:"sum"},
{headerName: "Transactions", field: "transactions", aggFunc:"sum"}
];
var gridOptions = {
columnDefs: columnDefs,
rowData: rowData,
groupSuppressAutoColumn: true,
onRowGroupOpened: getChildRows /* event created above */
}
document.addEventListener("DOMContentLoaded", function() {
var eGridDiv = document.querySelector('#myGrid');
new agGrid.Grid(eGridDiv, gridOptions);
});
</script>
</head>
<body>
<div id="myGrid" style="height: 100%;" class="ag-fresh"></div>
</body>
</html>
#Niall - any ideas on how to add the new rows more elegantly and retain status of group expansion?

Resources