Style cell based on values - Reactabular - reactjs

I would like to implement styling for cells based on values. If a cell has a value within a range, it should have different background colors.
Here is my implementation of the child component which just gets me the columns and does the sort.
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {sortColName} from '../../actions/index';
class DashboardColumns extends Component {
componentDidMount() {
this.props.onRef(this);
}
componentWillUnmount() {
this.props.onRef(undefined);
}
columnClick = (dataField) => {
const sortField = {
sortColName: dataField,
sortDir: this.props.sortColDir === 'asc' ? 'desc' : 'asc',
};
this.props.sortColName(sortField);
};
sortFormatter = (label, column) => {
if (column === this.props.sortCol) {
if (this.props.sortColDir === 'asc') {
return <i><span className="glyphicon glyphicon-triangle-top" />{label}</i>;
} else return <i><span className="glyphicon glyphicon-triangle-bottom" />{label}</i>;
}
return label;
};
percentageFormatter = cell => (<span>{cell} %</span>);
styleFormatter = (cell) => {
if (cell >= 95) {
return <span className="green-background">{cell}</span>;
} else if (cell < 95 && cell > 79) {
return <span className="yellow-background">{cell}</span>;
}
return <span className="red-background">{cell}</span>;
};
columns = [
{
property: 'database_name',
header: {
label: 'Database Name',
formatters: [label => this.sortFormatter(label, 'db_name')],
transforms: [
property => ({
onClick: () => this.columnClick('db_name')
})
]
}
}, {
property: 'target_address',
header: {
label: 'Target Address',
formatters: [label => this.sortFormatter(label, 'target_address')],
transforms: [
property => ({
onClick: () => this.columnClick('target_address')
})
]
}
}, {
property: 'db_type',
header: {
label: 'Database Type',
formatters: [label => this.sortFormatter(label, 'db_type')],
transforms: [
property => ({
onClick: () => this.columnClick('db_type')
})
]
}
}, {
property: 'environment_classification',
header: {
label: 'Environment',
formatters: [label => this.sortFormatter(label, 'environment_classification')],
transforms: [
property => ({
onClick: () => this.columnClick('environment_classification')
})
]
}
}, {
property: 'non_comp_acc',
header: {
label: '# of Non-Compliant Accounts',
formatters: [label => this.sortFormatter(label, 'non_compliant')],
transforms: [
property => ({
onClick: () => this.columnClick('non_compliant')
})
]
}
}, {
property: 'comp_acc',
header: {
label: '# of Compliant Accounts',
formatters: [label => this.sortFormatter(label, 'compliant')],
transforms: [
property => ({
onClick: () => this.columnClick('compliant')
})
]
}
}, {
property: 'percentage_compliant',
header: {
label: 'Percentage Compliant',
formatters: [label => this.sortFormatter(label, 'percentage_compliant')],
transforms: [
property => ({
onClick: () => this.columnClick('percentage_compliant')
})
]
},
cell: {
formatters: [this.percentageFormatter],
transforms: [
value => this.styleFormatter(value)
]
}
}];
render() {
return null;
}
}
const mapStateToProps = state => ({
sortCol: state.getSortColName.sort.sortColName,
sortColDir: state.getSortColName.sort.sortDir,
});
const mapDispatchToProps = dispatch => ({
sortColName: dataField => dispatch(sortColName(dataField)),
});
export default connect(mapStateToProps, mapDispatchToProps)(DashboardColumns);
Please advice. Also could someone help me out on the formatters stuff. I am getting what I want perfectly but is there a more cleaner code for this?

Set a transform like this
styleTransform = (cell) => {
if (cell >= 95) {
return { className: 'green-background' }
}
...
};
Issue at tracker: https://github.com/reactabular/reactabular/issues/341 .

Related

AgGrid cells don't re-render on refresh

This is the cell renderer for the 2 action buttons I'm passing to AgGrid. When I refresh the page, it loses its state and doesn't re-render them, but hits the function nevertheless.
const columnDefs: ColDef[] = useMemo(() => [
{
field: 'actions',
headerName: t('actions', { ns: 'common' }),
cellRendererSelector: (params: ICellRendererParams<IShop>) => ({
component: ActionsCell,
params: {
...params,
options: {
edit: {
id: 'editShop',
hasPermission: user.permissions.canEditShop,
href: (data: IShop) => appRoutes.editShop(router.query.companyId as string, data.id as string)
},
delete: {
id: 'deleteShop',
hasPermission: user.permissions.canDeleteShop,
onDeleteClick: (data: IShop) => handleClickOpen(data),
},
}
}
}),
cellStyle: agGridStyles.actionsCell
},
]
My AgGrid invocation:
<AgGridReact<IShop>
sideBar={sidebarConfig}
ref={gridRef}
containerStyle={agGridStyles.container}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
paginationPageSize={gridPageSize}
onGridReady={onGridReady}
/>
I tried spreading the options, in order to create a new reference to no avail:
options: {
...params.options,
edit: {
//...
}
}
Should I define the options object outside of the cell renderer:
const [options, setOptions] = useState<IOptions>({
edit: {
id: 'editShop',
hasPermission: user.permissions.canEditShop,
href: (data: IShop) => appRoutes.editShop(router.query.companyId as string, data.id as string)
},
delete: {
id: 'deleteShop',
hasPermission: user.permissions.canDeleteShop,
onDeleteClick: (data: IShop) => handleClickOpen(data),
},
});

Antd Tree component, how to add cache data

I have a problem with the Tree component of the Antd library. The problem is presented on the video. Namely that the component after changing the data tree renders anew and after selecting an option the previous ones are cleared. Does anyone have any idea how to solve this, so that after changing the data tree, the previous options that were selected are still selected?
import React, { useState } from 'react';
import { Tree } from 'antd';
import { Wrapper, TreeContainer } from './Tree.styled';
const treeData = [
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-0-0-0', },
{ title: '0-1-0-1', key: '0-0-0-1' },
{ title: '0-1-0-2', key: '0-0-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
{
title: '0-3',
key: '0-3',
children: [
{ title: '0-2-0-0', key: '0-2-0-0', },
{ title: '0-2-0-1', key: '0-2-0-1' },
{ title: '0-2-0-2', key: '0-2-0-2' },
],
},
{
title: '0-4',
key: '0-4',
children: [
{ title: '0-3-0-0', key: '0-3-0-0', },
{ title: '0-3-0-1', key: '0-3-0-1' },
{ title: '0-3-0-2', key: '0-3-0-2' },
],
},
{
title: '0-5',
key: '0-5',
children: [
{ title: '0-4-0-0', key: '0-4-0-0', },
{ title: '0-4-0-1', key: '0-4-0-1' },
{ title: '0-4-0-2', key: '0-4-0-2' },
],
},
];
const AntdTree = () => {
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
const [optionValue, setOptionValue] = useState<any>();
const tree = treeData.filter(filterValue => filterValue.key == (!!optionValue ? optionValue : filterValue.key)).map(data => data)
const onCheck = (checkedKeysValue: any) => {
console.log('onCheck', checkedKeysValue);
setCheckedKeys(checkedKeysValue);
};
return (
<>
<Wrapper>
<TreeContainer>
<select value={optionValue} onChange={e => setOptionValue(e.target.value)} >
<option value={'0-1'}>0-1</option>
<option value={'0-2'}>0-2</option>
<option value={'0-3'}>0-3</option>
<option value={'0-4'}>0-4</option>
<option value={'0-5'}>0-5</option>
</select>
<button onClick={() => setOptionValue('')} >Delete</button>
<Tree
checkable
onCheck={onCheck}
checkedKeys={checkedKeys}
treeData={tree}
/>
</TreeContainer>
</Wrapper>
</>
);
};
export default AntdTree;
Link to video with problem: https://youtu.be/BLEzQck3cZo
Thanks for your help !😊
onCheck callback in your case rewrite new values. You can save previous values using prevState in useState hook like so:
const onCheck = (checkedKeysValue: React.Key[], info: any) => {
console.log('onCheck', checkedKeysValue);
console.log('info', info);
if (info.checked) { // handle check case
setCheckedKeys(prevState => [...prevState, ...checkedKeysValue]);
} else { // handle uncheck case
setCheckedKeys(checkedKeysValue);
}
};

How to implement AddAdiditions in React Sematic UI using Hooks?

I want to have a drop down in my application which allows the user to add an item to the dropdown. I am using React Sematic UI.
Sematic UI Dropdown ALlowAdditions
I am new to react hooks and I want to know how I can implement the onChange and onAddition function using hooks.
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'
const options = [
{ key: 'English', text: 'English', value: 'English' },
{ key: 'French', text: 'French', value: 'French' },
{ key: 'Spanish', text: 'Spanish', value: 'Spanish' },
{ key: 'German', text: 'German', value: 'German' },
{ key: 'Chinese', text: 'Chinese', value: 'Chinese' },
]
class DropdownExampleAllowAdditions extends Component {
state = { options }
handleAddition = (e, { value }) => {
this.setState((prevState) => ({
options: [{ text: value, value }, ...prevState.options],
}))
}
handleChange = (e, { value }) => this.setState({ currentValue: value })
render() {
const { currentValue } = this.state
return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}
export default DropdownExampleAllowAdditions
Any help would be greatly appreciated. Thanks in advance :)
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
const options = [
{ key: "English", text: "English", value: "English" },
{ key: "French", text: "French", value: "French" },
{ key: "Spanish", text: "Spanish", value: "Spanish" },
{ key: "German", text: "German", value: "German" },
{ key: "Chinese", text: "Chinese", value: "Chinese" }
];
const DropDownWithHooks = () => {
const [dropDownOptions, setDropDownOptions] = useState(options);
const [currentValue, setCurrentValue] = useState("");
const handleAddition = (e, { value }) => {
setDropDownOptions((prevOptions) => [
{ text: value, value },
...prevOptions
]);
};
const handleChange = (e, { value }) => setCurrentValue(value);
return (
<Dropdown
options={dropDownOptions}
placeholder="Choose Language"
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={handleAddition}
onChange={handleChange}
/>
);
};
export default DropDownWithHooks;
Working Sandbox

How to convert function component to class component in fluent UI?

I am creating multi select drop down in Office fabrics.I saw the code.It contain the functional component.I want to change in class component.and How can we store the selected options in state variable?
please guide me.I am new in spfx share-point.
Code given below:-
import * as React from 'react';
import { Dropdown, DropdownMenuItemType, IDropdownOption, IDropdownStyles } from 'office-ui-fabric-react/lib/Dropdown';
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
const DropdownControlledMultiExampleOptions = [
{ key: 'fruitsHeader', text: 'Fruits', itemType: DropdownMenuItemType.Header },
{ key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' },
{ key: 'orange', text: 'Orange', disabled: true },
{ key: 'grape', text: 'Grape' },
{ key: 'divider_1', text: '-', itemType: DropdownMenuItemType.Divider },
{ key: 'vegetablesHeader', text: 'Vegetables', itemType: DropdownMenuItemType.Header },
{ key: 'broccoli', text: 'Broccoli' },
{ key: 'carrot', text: 'Carrot' },
{ key: 'lettuce', text: 'Lettuce' },
];
export const DropdownControlledMultiExample: React.FunctionComponent = () => {
const [selectedKeys, setSelectedKeys] = React.useState<string[]>([]);
const onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
if (item) {
setSelectedKeys(
item.selected ? [...selectedKeys, item.key as string] : selectedKeys.filter(key => key !== item.key),
);
}
};
return (
<Dropdown
placeholder="Select options"
label="Multi-select controlled example"
selectedKeys={selectedKeys}
onChange={onChange}
multiSelect
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
/>
);
};
You can do the following:
export class DropdownControlledMultiExample extends React.Component {
state = {
selectedKeys: []
}
onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
if (item) {
this.setState({
selectedKeys:
item.selected
? [...this.state.selectedKeys, item.key as string]
: this.state.selectedKeys.filter(key => key !== item.key),
});
}
};
render() {
return (
<Dropdown
placeholder="Select options"
label="Multi-select controlled example"
selectedKeys={this.state.selectedKeys}
onChange={this.onChange}
multiSelect
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
/>
);
}
};

Add new row with a key press like 'enter'

I would like to add a key listener with 'enter' key to "onRowAdd" action from material-table on react,
Could be able to call the function outside the table props and add a normal js listener to key enter for launch the function?
So i searched on the doc of material-table and nothing similar can help me, anyone have some idea how i can fix it?
thanks
import React, { useEffect, useState } from 'react'
import MaterialTable from 'material-table'
import axios from 'axios'
var emitter = require('../config/global_emitter')
export default function MaterialTableDemo(props) {
const [state, setState] = useState({
columns: [
{ title: 'Item', field: 'item' },
{ title: 'Quantity', field: 'quantity', type: 'numeric' },
{ title: 'Description', field: 'description' },
{ title: 'Price', field: 'price', type: 'numeric' },
{
title: 'Location',
field: 'location',
lookup: { 34: 'Batman', 63: 'Back Store' },
},
],
data: []
});
useEffect(() => {
setState({...state, data:[]})
const user = {
name: props.userSelected
}
axios.post('api', user)
.then(e => {
if (e.data !== ''){
setState({...state, data: e.data})
}
})
},[props.userSelected])
const handleUpdate = (data) => {
const upload = {
items: data,
name: props.userSelected
}
axios.post('api', upload)
.then((e) => {
if (e.status === 200){
emitter.emit('confirmMessage', 'Updated list correctly')
}
})
}
return (
<MaterialTable
title={props.userSelected + '´s items ordered'}
columns={state.columns}
data={state.data}
options={{
headerStyle: {
backgroundColor: '#01579b',
color: '#FFF'
},
rowStyle: {
opacity: 1,
animationName: 'fadeInOpacity',
animationIterationCount: 1,
animationTimingFunction: 'ease-in',
animationDuration: '2s'
}
}}
onKeyDown={(ev) => {
console.log(`Pressed keyCode ${ev.key}`);
if (ev.key === 'Enter') {
// Do code here
ev.preventDefault();
}
}}
editable={{
onRowAdd: newData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
addRow(newData)
}, 600);
}),
onRowUpdate: (newData, oldData) =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data[data.indexOf(oldData)] = newData;
handleUpdate(data)
setState({ ...state, data });
}, 600);
}),
onRowDelete: oldData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data.splice(data.indexOf(oldData), 1);
handleUpdate(data)
setState({ ...state, data });
}, 600);
}),
}}
/>
);
}

Resources