AG-420 Improve React implementation
@@ -65,10 +65,10 @@ class TopMoversGrid extends Component {
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.props.rowData}
|
||||
enableSorting="true"
|
||||
enableSorting
|
||||
enableFilter="false"
|
||||
animateRows="true"
|
||||
enableImmutableMode="true"
|
||||
animateRows
|
||||
deltaRowDataMode
|
||||
getRowNodeId={this.getRowNodeId}
|
||||
|
||||
// events
|
||||
|
||||
@@ -11,6 +11,7 @@ import FullWidthComponentExample from "./fullWidthExample/FullWidthComponentExam
|
||||
import GroupedRowInnerRendererComponentExample from "./groupedRowInnerRendererExample/GroupedRowInnerRendererComponentExample";
|
||||
import FilterComponentExample from "./filterComponentExample/FilterComponentExample";
|
||||
import MasterDetailExample from "./masterDetailExample/MasterDetailExample";
|
||||
import SimpleReduxExample from "./simpleReduxExample/SimpleReduxExample";
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
@@ -49,6 +50,7 @@ class App extends Component {
|
||||
<li role="presentation" className={this.state.example === 'group-row' ? 'active' : null} onClick={() => this.setExample("group-row")}><a href="#">Grouped Row Inner Renderer Example</a></li>
|
||||
<li role="presentation" className={this.state.example === 'filter' ? 'active' : null} onClick={() => this.setExample("filter")}><a href="#">Filters Component Example</a></li>
|
||||
<li role="presentation" className={this.state.example === 'master-detail' ? 'active' : null} onClick={() => this.setExample("master-detail")}><a href="#">Master Detail Example</a></li>
|
||||
<li role="presentation" className={this.state.example === 'simple-redux' ? 'active' : null} onClick={() => this.setExample("simple-redux")}><a href="#">Simple Redux Example</a></li>
|
||||
</ul>)
|
||||
}
|
||||
|
||||
@@ -78,6 +80,9 @@ class App extends Component {
|
||||
case 'master-detail':
|
||||
example = <MasterDetailExample/>;
|
||||
break;
|
||||
case 'simple-redux':
|
||||
example = <SimpleReduxExample/>;
|
||||
break;
|
||||
default:
|
||||
example = <RichGridExample/>;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 606 B |
|
Before Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 174 B |
|
Before Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 289 B |
|
Before Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 136 B |
|
Before Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 222 B |
|
Before Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 739 B |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 902 B |
|
Before Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 394 B |
|
Before Width: | Height: | Size: 893 B |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 570 B |
@@ -67,7 +67,7 @@ export default class FilterComponentExample extends Component {
|
||||
return (
|
||||
<div style={{height: 400, width: 945}}
|
||||
className="ag-fresh">
|
||||
<h1>Group Row Renderer Example</h1>
|
||||
<h1>Filter Component Example</h1>
|
||||
<button style={{marginBottom: 10}} onClick={this.onClicked}>Filter Instance Method</button>
|
||||
<AgGridReact
|
||||
// properties
|
||||
|
||||
106
src/simpleReduxExample/GridComponent.jsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import {connect} from "react-redux";
|
||||
// take this line out if you do not want to use ag-Grid-Enterprise
|
||||
import "ag-grid-enterprise";
|
||||
|
||||
import {updateRowSelection} from "./gridDataActions";
|
||||
|
||||
/*
|
||||
* This component serves to display the row data (provided by redux)
|
||||
*/
|
||||
class GridComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
columnDefs: [
|
||||
{headerName: 'Symbol', field: 'symbol'},
|
||||
{headerName: 'Price', field: 'price'},
|
||||
{headerName: 'Group', field: 'group'}
|
||||
]
|
||||
};
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
this.onSelectionChanged = this.onSelectionChanged.bind(this);
|
||||
this.setGroupingEnabled = this.setGroupingEnabled.bind(this);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
|
||||
// set the initial group state
|
||||
this.setGroupingEnabled(false);
|
||||
}
|
||||
|
||||
// on selection publish selected row ids
|
||||
onSelectionChanged() {
|
||||
let selectedRowNodes = this.gridApi.getSelectedNodes();
|
||||
let selectedIds = selectedRowNodes.map((rowNode) => rowNode.id);
|
||||
|
||||
this.props.dispatch(updateRowSelection(selectedIds));
|
||||
}
|
||||
|
||||
setGroupingEnabled(enabled) {
|
||||
if (enabled) {
|
||||
this.columnApi.addRowGroupColumn('group');
|
||||
this.columnApi.setColumnVisible('group', false);
|
||||
this.columnApi.setColumnVisible('symbol', false);
|
||||
} else {
|
||||
this.columnApi.removeRowGroupColumn('group');
|
||||
this.columnApi.setColumnVisible('group', true);
|
||||
this.columnApi.setColumnVisible('symbol', true);
|
||||
}
|
||||
}
|
||||
|
||||
// row data will be provided via redux on this.props.rowData
|
||||
// we bind to this and using "deltaRowDataMode" the grid will only re-render rows that have changed
|
||||
// this requires each row to have a uniquely identifying property - in this case the row data "symbol" (see getRowNodeId)
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 400, width: 945, marginTop: 15}}
|
||||
className="ag-fresh">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.props.rowData}
|
||||
|
||||
deltaRowDataMode
|
||||
enableStatusBar
|
||||
animateRows
|
||||
enableColResize
|
||||
rowSelection="multiple"
|
||||
enableRangeSelection
|
||||
groupColumnDef={{
|
||||
headerName: 'Symbol',
|
||||
cellRenderer: 'group',
|
||||
field: 'symbol'
|
||||
}}
|
||||
groupDefaultExpanded="1"
|
||||
enableSorting
|
||||
getRowNodeId={(data) => data.symbol}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}
|
||||
onSelectionChanged={this.onSelectionChanged}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// pull off row data changes
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
rowData: state.rowData
|
||||
}
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{withRef: true}
|
||||
)(GridComponent);
|
||||
174
src/simpleReduxExample/HeaderComponent.jsx
Normal file
@@ -0,0 +1,174 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
// take this line out if you do not want to use ag-Grid-Enterprise
|
||||
import "ag-grid-enterprise";
|
||||
|
||||
import {updateRowData} from "./gridDataActions";
|
||||
|
||||
/*
|
||||
* This component serves both to host the demo controls, which in turn will drive row data state changes
|
||||
*/
|
||||
class HeaderComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.addFiveItems = this.addFiveItems.bind(this);
|
||||
this.removeSelected = this.removeSelected.bind(this);
|
||||
this.updatePrices = this.updatePrices.bind(this);
|
||||
this.setGroupingEnabled = this.setGroupingEnabled.bind(this);
|
||||
this.setItemVisible = this.setItemVisible.bind(this);
|
||||
this.setSelectedToGroup = this.setSelectedToGroup.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// provide the initial data to the store (which in turn will populate the grid)
|
||||
this.props.dispatch(updateRowData(this.createRowData()));
|
||||
}
|
||||
|
||||
// add five new items to the row data and publish the change
|
||||
addFiveItems() {
|
||||
let newRowData = this.props.rowData.slice();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let newItem = this.createItem();
|
||||
newRowData.push(newItem);
|
||||
}
|
||||
|
||||
this.props.dispatch(updateRowData(newRowData));
|
||||
}
|
||||
|
||||
// remove selected rows from the data set and publish the change
|
||||
removeSelected() {
|
||||
let newRowData = this.props.rowData.filter((dataItem) => (this.props.rowSelection.indexOf(dataItem.symbol) < 0));
|
||||
this.props.dispatch(updateRowData(newRowData));
|
||||
}
|
||||
|
||||
// group data based on selection and publish the change
|
||||
setSelectedToGroup(newGroup) {
|
||||
let selectedIds = this.props.rowSelection;
|
||||
let newRowData = this.props.rowData.map((dataItem) => {
|
||||
let itemSelected = selectedIds.indexOf(dataItem.symbol) >= 0;
|
||||
if (itemSelected) {
|
||||
return {
|
||||
// symbol and price stay the same
|
||||
symbol: dataItem.symbol,
|
||||
price: dataItem.price,
|
||||
// group gets the group
|
||||
group: newGroup
|
||||
};
|
||||
} else {
|
||||
return dataItem;
|
||||
}
|
||||
});
|
||||
|
||||
this.props.dispatch(updateRowData(newRowData));
|
||||
}
|
||||
|
||||
// randomly update prices in the row data and publish the change
|
||||
updatePrices() {
|
||||
let newRowData = [];
|
||||
this.props.rowData.forEach(function (item) {
|
||||
newRowData.push({
|
||||
// use same symbol as last time, this is the unique id
|
||||
symbol: item.symbol,
|
||||
// group also stays the same
|
||||
group: item.group,
|
||||
// add random price
|
||||
price: Math.floor(Math.random() * 100)
|
||||
});
|
||||
});
|
||||
|
||||
this.props.dispatch(updateRowData(newRowData));
|
||||
}
|
||||
|
||||
|
||||
setGroupingEnabled(enabled) {
|
||||
// let the parent (and the grid in turn) know about the grouping state change
|
||||
this.props.setGroupingEnabled(enabled);
|
||||
|
||||
// toggle the grouping buttons visibility
|
||||
this.setItemVisible('groupingOn', !enabled);
|
||||
this.setItemVisible('groupingOff', enabled);
|
||||
}
|
||||
|
||||
setItemVisible(id, visible) {
|
||||
let element = document.querySelector('#' + id);
|
||||
element.style.display = visible ? null : 'none';
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{marginTop: 15}}>
|
||||
<button onClick={this.addFiveItems}>Add Five Items</button>
|
||||
<button onClick={this.removeSelected}>Remove Selected</button>
|
||||
<button onClick={this.updatePrices}>Update Prices</button>
|
||||
|
||||
<span style={{padding: 10}}/>
|
||||
<button id="groupingOn" onClick={() => this.setGroupingEnabled(true)}>Turn Grouping On</button>
|
||||
<button id="groupingOff" style={{display: "none"}} onClick={() => this.setGroupingEnabled(false)}>Turn
|
||||
Grouping Off
|
||||
</button>
|
||||
<span style={{padding: 10}}/>
|
||||
<span style={{border: "1px solid lightgrey", padding: 4}}>
|
||||
Group Selected:
|
||||
<button onClick={() => this.setSelectedToGroup('A')}>A</button>
|
||||
<button onClick={() => this.setSelectedToGroup('B')}>B</button>
|
||||
<button onClick={() => this.setSelectedToGroup('C')}>C</button>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// the following methods are for creating dummy row data
|
||||
createRowData() {
|
||||
let rowData = [];
|
||||
|
||||
for (let i = 0; i < 14; i++) {
|
||||
let newItem = this.createItem();
|
||||
rowData.push(newItem);
|
||||
}
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
||||
createItem() {
|
||||
return {
|
||||
group: 'A',
|
||||
symbol: this.createUniqueRandomSymbol(),
|
||||
price: Math.floor(Math.random() * 100)
|
||||
};
|
||||
}
|
||||
|
||||
// creates a unique symbol, eg 'ADG' or 'ZJD'
|
||||
createUniqueRandomSymbol() {
|
||||
let symbol;
|
||||
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
let isUnique = false;
|
||||
while (!isUnique) {
|
||||
symbol = '';
|
||||
// create symbol
|
||||
for (let i = 0; i < 3; i++) {
|
||||
symbol += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
// check uniqueness
|
||||
isUnique = true;
|
||||
this.props.rowData.forEach(function (oldItem) {
|
||||
if (oldItem.symbol === symbol) {
|
||||
isUnique = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
// pull off row data and selected row changes
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
rowData: state.rowData,
|
||||
rowSelection: state.rowSelection
|
||||
}
|
||||
}
|
||||
)(HeaderComponent);
|
||||
40
src/simpleReduxExample/SimpleReduxExample.jsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React, {Component} from "react";
|
||||
import {Provider} from "react-redux";
|
||||
import {createStore} from "redux";
|
||||
// take this line out if you do not want to use ag-Grid-Enterprise
|
||||
import "ag-grid-enterprise";
|
||||
|
||||
import HeaderComponent from "./HeaderComponent";
|
||||
import GridComponent from "./GridComponent";
|
||||
|
||||
import gridData from "./gridDataReducer";
|
||||
|
||||
let store = createStore(gridData);
|
||||
|
||||
/*
|
||||
* This component serves as a container for both the header and grid components. It's primarily here to act as a container
|
||||
* for the redux Provider
|
||||
*/
|
||||
export default class SimpleReduxExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.setGroupingEnabled = this.setGroupingEnabled.bind(this);
|
||||
}
|
||||
|
||||
setGroupingEnabled(enabled) {
|
||||
this.grid.setGroupingEnabled(enabled);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<div>
|
||||
<h1>Simple Redux Example using ag-Grid's deltaRowMode</h1>
|
||||
<HeaderComponent setGroupingEnabled={this.setGroupingEnabled} />
|
||||
<GridComponent ref={ grid => { this.grid = grid ? grid.getWrappedInstance() : null }} />
|
||||
</div>
|
||||
</Provider>
|
||||
)
|
||||
}
|
||||
};
|
||||
13
src/simpleReduxExample/gridDataActions.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
export function updateRowData(rowData) {
|
||||
return {
|
||||
type: 'ROW_DATA_CHANGED',
|
||||
rowData
|
||||
}
|
||||
}
|
||||
|
||||
export function updateRowSelection(rowSelection) {
|
||||
return {
|
||||
type: 'ROW_SELECTION_CHANGED',
|
||||
rowSelection
|
||||
}
|
||||
}
|
||||
16
src/simpleReduxExample/gridDataReducer.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
export default (state = {rowData: [], rowSelection: []}, action) => {
|
||||
switch (action.type) {
|
||||
case 'ROW_DATA_CHANGED':
|
||||
return {
|
||||
...state,
|
||||
rowData: action.rowData,
|
||||
};
|
||||
case 'ROW_SELECTION_CHANGED':
|
||||
return {
|
||||
...state,
|
||||
rowSelection: action.rowSelection,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||