Conditional styling on row for dynamic cell value - reactjs

Conditional row styling on ag grid where I want to do rowstyle on user choice of cell value
gridoptions.getRowStyle = function(params) {
if (params.node.data === 'cell value typed by user in external/custom component i.e outside grid') {
return { 'background': value selected by user in cutom componet outside grid };
}
}

#sandeep's answer works perfectly. I just want to chime in another way to solve the problem which is to use context. context is just another javascript object which contains any information that you want to share within AgGrid. The data will be accessible in most AgGrid callbacks for example cell renderers, editors's render callback and in your case getRowStyle callback
const sickDays = // data from external component
const color = // data from external component
<AgGridReact
getRowStyle={(params) => {
const { styles, data } = params.context;
if (params.node.data["sickDays"] === data.sickDays) {
return { backgroundColor: styles.color };
}
return null;
}}
context={{
data: { sickDays },
styles: { color }
}}
/>
Live Demo

here is a plunkr which should give you idea to solve the problem. since i don't know much about your component hence i used two input boxes with button to set background color to row but you can use complex styles as well.
I am using api.redrawRows() since the operation we are performing needs to work on row.

Related

Keen Slider React Component Always One Step Behind

I installed the keen-slider library in my React project, and used the code from the App.js file in this example to set up a slider with page dots and navigation arrows. I am trying to modify that code, by passing in an array of React components, the size of which can be changed when the user selects or deselects options.
The problem is, the slider's dot count and arrow configuration always lags one step behind. If I move from 1 (default) to 2 pages selected, the rendered dot count stays at 1. When I increase to 3, it moves to 2. If I then decrease to 2, it goes to 3. It only catches up if I interact with the slider. In my App component's return, I place the slider as {keenSlider(outputComponentArray)}. To get outputComponentArray, I have some divs with onClick functions that toggle each page type's selected state. This array:
var selectedResultsConfig = [
['Proposal', outputs.proposal, resultSelectorProposal, setResultSelectorProposal],
['Map', outputs.map, resultSelectorMap, setResultSelectorMap],
['Front Page', outputs.frontPage, resultSelectorFrontPage, setResultSelectorFrontPage],
['Collage', outputs.collage, resultSelectorCollage, setResultSelectorCollage],
['Price Letter', outputs.priceLetter, resultSelectorPriceLetter, setResultSelectorPriceLetter],
['Line Items', outputs.lineItems, resultSelectorLineItems, setResultSelectorLineItems]
]
establishes what name, page component (in the 'outputs' object), and toggle state/setting function correspond to each other, then these buttons are rendered with .map on this array, like so:
{selectedResultsConfig.map((item, index) => {
return <>
{(index === 0) ? null : <> </>}
<div className={item[2] ? 'resultSelectorButton selectedButton' : 'resultSelectorButton'} onClick={() => { resultSelectToggle(item[0]) }}>
<Icon path={item[2] ? mdiCheckboxMarked : mdiCheckboxBlankOutline} size={1} color='#ecd670' />
<h2>{item[0]}</h2>
</div>
</>
})}
and their onClick function does the toggling like this:
function resultSelectToggle(button) {
if (screen === 'proposals') {
for (let i = 0; i < selectedResultsConfig.length; i++) {
if (button === selectedResultsConfig[i][0]) {
selectedResultsConfig[i][3](!selectedResultsConfig[i][2])
}
}
}
}
and then I have a useEffect hook that goes off after those toggles and sets up the final component array, which is fed to keen-slider:
//after the result selector button is toggled
useEffect(() => {
var tempComponentArray = [];
if (screen === 'proposals') {
for (let i = 0; i < selectedResultsConfig.length; i++) {
if (selectedResultsConfig[i][2]) {
tempComponentArray.push(selectedResultsConfig[i][1])
}
}
}
setOutputComponentArray(tempComponentArray);
}, [resultSelectorProposal, resultSelectorMap, resultSelectorFrontPage, resultSelectorCollage, resultSelectorPriceLetter, screen])
I'm not the most experienced with React, and I already know there are better ways of doing some of this, but it's not clear to me what is causing my issue. I was having a similar issue once that was fixed with useEffect, but I've already implemented that here. Any help would be appreciated, thanks.
I have made significant modifications to my original code to simplify it, and I originally passed keenSlider a functional component, but still the problem persists.

Set value immediately after another one have been set in Reanimated 2

I am using Reanimated 2 to build a game with React Native its performance is incredibly good but I have a problem.
I am using a shared value to animate a View as we all know setting the value of the shared value will automatically change the style of the View, my problem is that let's say it will be a Button that the user presses to give the View an elevation simply by changing a shared value used in the animated style of the View, the elevation is simply translation in the y axis.
The elevation value is 0 at first. The user clicks the button the value changes to for example 500 immediately with no transition and no animation, the View will immediately show at 500 above its starting position. And from 500 the View will drop back to 0 with animation.
I tried the code below but no help.
const elevation = useSharedValue(0);
const handleClick = () => {
elevation.value = 500;
elevation.value = withTiming(0, { duration: 1000 });
}
const viewAnimatedStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: elevation.value,
}
]
}))
when pressing the button the view doesn't move, it seems that Reanimated skips the first elevation.value assignment, and since the second assignment is to 0 (the same old value) the View doesn't move.
[Edit] Animated.View is imported from Reanimated 2 and used. I left it out for simplicity.
You need to use <Animated.View> for the useAnimatedStyle, If you are now using It will not be working correctly.
function App() {
const width = useSharedValue(50);
const animatedStyle = useAnimatedStyle(() => {
return {
width: width.value,
};
});
// attach animated style to a View using style property
return <Animated.View style={[styles.box, animatedStyle]} />;
}

React-data-grid : Changing a row color depending on a value of the row

My component Test is called and gets in props an object containing datas from a mysql request (Select * from db.mytable). I store this.props.data in a state and render it in a ReactDataGrid.
What I'm trying to do is to update and change color of a row when a value of a cell is changed in my ReactDataGrid. For example, if a user right clicks on a rows, a context menu appear and he has the choice between Check and Uncheck. When he clicks on Check, i want to update the row and make it appear green.
I've got a database where I store the Checked state so when the user refreshes the page, the line should stay green.
How may I do this?
So when I click check in the context menu this function is called, it will update my state table containing the rows :
//right click then check
rowCheck = (rowIdx) => {
var tableState=this.state.tableState.concat([])
tableState[rowIdx.rowIdx].CHECKED='Y'
this.setState({tableState})
}
the RowsRenderer function :
RowRenderer = ({ renderBaseRow, ...props }) => {
const color = this.state.tableState[props.idx].CHECKED==='Y' ? "blue" : "";
return <div style={{color}}>{renderBaseRow(props)}</div>;
};
the data-grid :
<ReactDataGrid
columns={this.state.column}
rowGetter={i => this.state.tableState[i]}
rowsCount={this.state.tableState.length}
minHeight={500}
enableCellSelect={true}
onGridRowsUpdated={this.onGridRowsUpdated}
cellNavigationMode={'changeRow'}
rowRenderer={this.RowRenderer}
contextMenu={
<ExampleContextMenu
onRowCheck={(e, {rowIdx})=>this.rowCheck({rowIdx})}
onRowUncheck={(e, { rowIdx }) => this.rowUncheck({rowIdx})}
/>
}
RowsContainer={ContextMenuTrigger}
rowSelection={{
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: this.onRowsSelected,
onRowsDeselected: this.onRowsDeselected,
selectBy: {
indexes: this.state.selectedIndexes
}
}}
/>
Adding to the above solution:
I wanted to change the row's background-color rather than the color itself so I ended up adding a class to the div wrapper instead of style.
<div className={classnames({ 'focused-row': focused })}>{data.renderBaseRow(data)}</div>
Then in my css I added
.focused-row .react-grid-Cell {
background-color: #f5deff !important;
}
Otherwise the cell's background-color was overriding the row's

How to prevent row selection after clicking on link inside custom rendered cell in AgGrid

I am using AgGrid and have rowSelection="multiple" on my grid, have {cellRendererFramework: PrintCell} on the last column, which is a small component that displays a link.
I want it so, when I click on the link inside PrintCell, a certain action should be executed, without altering the the state of the grid itself, and keep the current selected lines selected without making the row containing the link selected. I tried doing event.stopPropagation and event.preventDefault to prevent the parent row from getting selected, to no avail.
Any Idea how to achieve this ? thanks
Updated for June 2018:
The API for Ag-Grid has changed. The key change is that there needs to be a change to e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection from within the onCellFocused event of the grid
Here is a full solution that uses a reusable cell renderer to create actions or buttons at the end of a row that won't trigger row selection. This solution assumes that you are using the React version of ag-grid and that you are using a custom cell renderer.
// class fields
disableClickSelectionRenderers = ['rowActionRenderer'];
// columns defs
...
{headerName: '', field: 'someButton',
suppressMenu: true, suppressFilter: true, suppressSorting: true,
suppressMovable: true,
suppressNavigable: true, suppressResize: true,
cellRenderer: 'rowActionRenderer',
cellRendererParams: {
icon: <i className="fa fa-pencil"/>,
onClick: (e, props) => {
// do the action
},
},
},
render() {
<AgGridReact
columnDefs={...}
// ... other properties
onCellFocused={e => {
if (e.column && this.disableClickSelectionRenderers.includes(e.column.colDef.cellRenderer)) {
e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection = true;
}
else {
e.api.gridOptionsWrapper.gridOptions.suppressRowClickSelection = false;
}
}}
}
Since the row click is a specified behaviour it might be easier to perhaps use the checkbox selection and disable the focus row selection entirely. But if you want to keep with this path I generated the required behaviour by intercepting the event in the cell Focus and blocking row selection there.
private onCellFocused($event) {
if($event.column && $event.column.colId == "commentid"){
this.gridOptions.suppressRowClickSelection = true;
} else {
this.gridOptions.suppressRowClickSelection = false;
}
This switches the row selection event of entirely but only if you select the column where you don't want the behaviour to occur (caveats: angular 2 example and we have wrapped the ag-grid inside our own component.
Hope this helps...
For TS + Angular
use it inside your rowclick method
Incase if you want to ignore a particular cell this piece of code can help you
if (!(
this.gridApi?.getFocusedCell()?.column.getColId() ===
'columnName')) {
//your code here
}
the gridApi can probably be got from the onGridReady method

How to rerender entire single row in react-table?

I have a react-table component in my app and pass there next props:
<ReactTable
data={this.props.words}
columns={columns}
getTrProps={changing_state_func}
/>
changing_state_func is a function that changes state of the component that wraps react-table. Specifically, this function fills an array that contains ids of the data objects for rows. So I'd like to highlight the rows with the data for those ids... Cannot figure it out how to do it with this particular datagrid. Maybe somebody has the experience working with react-table and example on this case.
I'm not sure what actually you're trying to do, but here are my thoughts.
getTrProps is used to pass props to the table's rows.
So according the module docs, you can pass whatever you want.
The example shows how you can change the color of the rows, those meet specific condition:
// Any Tr element will be green if its (row.age > 20)
<ReactTable
getTrProps={(state, rowInfo, column) => {
return {
style: {
background: rowInfo.age > 20 ? 'green' : 'red'
}
}
}}
/>
Fixes to the react-table 5.0.2 allow to have access to the table's instance, and the problem can be solved by calling .forceUpdate() method on the table's instance. changing_state_func in this case may look like this:
changing_state_func = (state, rowInfo, column, instance) => {
if (!rowInfo) return {}
return {
style: {
background: (this.state.rowsIdsArray.includes(rowInfo.row.id)) ? 'green' : null
},
onClick: () => {
this.setState({rowsIdsArray: this.state.rowsIdsArray.concat([rowInfo.row.id])});
instance.forceUpdate()
}
}
}
Thanks to the Tanner Linsley for responsiveness and quick fixes.

Resources