Compare commits

...

37 Commits

Author SHA1 Message Date
Alberto
d2b92b4c9a Release 13.3.0 2017-10-02 14:55:11 +02:00
Sean Landsman
c8267730bf Update code to match latest changes 2017-09-28 13:56:46 +01:00
Alberto
3992e3e928 v 13.2.0 2017-09-19 10:17:51 +01:00
Alberto
8409183d6b v 13.2.0 2017-09-19 09:00:11 +01:00
Sean Landsman
7075f57d88 Tidy examples 2017-09-18 16:03:27 +01:00
Sean Landsman
ad6bc068b2 Improve react examples 2017-09-15 16:56:08 +01:00
seanlandsman
c4310c2768 Merge pull request #32 from unformatt/patch-1
Fixes typo in README
2017-09-13 14:35:08 +01:00
Alberto
2228a8d0c9 Merge branch 'master' into latest 2017-09-08 09:40:53 +01:00
Matt
966fa0fe69 Update README.md 2017-09-07 18:37:15 -04:00
Sean Landsman
9528d5a5bc Move per col icons to grid based 2017-09-04 10:39:17 +01:00
Alberto
3b5eaac21a Merge branch 'latest' into 13.1.0
# Conflicts:
#	aot/dist/agGridColumn.ngfactory.ts
#	aot/dist/agGridColumn.ngsummary.json
#	aot/dist/agGridNg2.ngfactory.ts
#	aot/dist/agGridNg2.ngsummary.json
#	aot/dist/aggrid.module.ngfactory.ts
#	aot/dist/aggrid.module.ngsummary.json
#	aot/dist/baseComponentFactory.ngsummary.json
#	aot/dist/interfaces.ngsummary.json
#	aot/dist/ng2ComponentFactory.ngsummary.json
#	aot/dist/ng2FrameworkComponentWrapper.ngsummary.json
#	aot/dist/ng2FrameworkFactory.ngsummary.json
#	aot/main.ngsummary.json
#	aot/src/agGridColumn.ngfactory.ts
#	aot/src/agGridColumn.ngsummary.json
#	aot/src/agGridNg2.ngfactory.ts
#	aot/src/agGridNg2.ngsummary.json
#	aot/src/aggrid.module.ngfactory.ts
#	aot/src/aggrid.module.ngsummary.json
#	aot/src/baseComponentFactory.ngsummary.json
#	aot/src/interfaces.ngsummary.json
#	aot/src/ng2ComponentFactory.ngsummary.json
#	aot/src/ng2FrameworkComponentWrapper.ngsummary.json
#	aot/src/ng2FrameworkFactory.ngsummary.json
2017-09-01 14:02:24 +01:00
Sean Landsman
73cc989512 AG-730 New example for redux 2017-08-31 17:17:26 +01:00
Alberto
5a45846cb7 Release 13.0.1 2017-08-29 15:27:33 +02:00
Petyo Ivanov
2d8d5b125e Removed legacy padding 2017-08-29 13:34:18 +03:00
Alberto
818b7798ee Merge branch 'latest' into 13.0.0
# Conflicts:
#	package.json
2017-08-25 16:59:25 +02:00
Sean Landsman
15ba8d7e60 Rename cellFormatter to valueFormatter 2017-08-23 14:04:13 +01:00
Alberto
eab958c3e9 Releasing 13.0.0 2017-08-23 11:35:39 +01:00
Sean Landsman
3a17b7f638 AG-668 Update all README.md to point to appropriate plunker/seed 2017-08-21 11:45:09 +01:00
Sean Landsman
734d39e2d7 AG-676 Move framework examples into parent folder for easier exclusion 2017-08-17 11:04:12 +01:00
Sean Landsman
0d7cace354 Add example for keypress in editors
https://github.com/ag-grid/ag-grid-react/issues/60
2017-08-10 16:02:03 +01:00
Sean Landsman
fa0881bfcf Merge remote-tracking branch 'origin/latest' into latest 2017-08-10 15:51:05 +01:00
Sean Landsman
62b9e3582a Add example for keypress in editors
https://github.com/ag-grid/ag-grid-react/issues/60
2017-08-10 15:50:54 +01:00
Petyo Ivanov
949797d4be rename repo from ceolter to ag-grid 2017-08-04 12:23:47 +01:00
Sean Landsman
a869fe3819 CI Work 2017-08-02 13:48:39 +01:00
Sean Landsman
c611af4f39 CI Work 2017-08-02 13:15:55 +01:00
Sean Landsman
7cab3190ae CI Work 2017-08-02 12:19:07 +01:00
Sean Landsman
71fe653fcb CI Work 2017-08-02 11:55:18 +01:00
Sean Landsman
ba1c213ce0 Change selectAll to use refs to expand on example 2017-07-27 08:17:15 +01:00
Sean Landsman
46217c9ad7 Fix sorting issue 2017-07-26 12:10:12 +01:00
Sean Landsman
017642e4d7 AG-643 Tidy React examples 2017-07-25 12:47:47 +01:00
Sean Landsman
79b0eda61b AG-643 Tidy React examples 2017-07-25 12:47:07 +01:00
Sean Landsman
a70f248af5 AG-642 Remove deprecation warning in preparation for 16.x 2017-07-25 12:46:21 +01:00
Alberto
32142b435b v12 Hot fixes 2017-07-21 12:10:00 +02:00
Alberto
d71781899d AG-618 Fixing floating filter issue. Also allowing for gulp watch of Angular and React 2017-07-20 13:59:16 +02:00
Sean Landsman
9560f86bf5 Updated readme 2017-07-19 10:30:28 +01:00
Alberto
9f4b270884 New release branch, everything compiles 2017-07-13 11:25:34 +01:00
John Masterson
e5627d8b9f Added links to ReadMe 2017-07-11 17:07:57 +01:00
47 changed files with 1260 additions and 430 deletions

View File

@@ -4,7 +4,14 @@ ag-Grid React Example
Examples of running ag-Grid inside React application.
See the [www.ag-grid.com](http://www.ag-grid.com).
See [www.ag-grid.com](http://www.ag-grid.com) for an overview and full documentation.
Frameworks Supported
====================
Framework specific Getting Started guides:
[Angular 1](https://www.ag-grid.com/best-angularjs-data-grid/) | [Angular 2](https://www.ag-grid.com/best-angular-2-data-grid/) | [Aurelia](https://www.ag-grid.com/best-aurelia-data-grid/)
[Javascript](https://www.ag-grid.com/best-javascript-data-grid/) | [React](https://www.ag-grid.com/best-react-data-grid/) | [TypeScript](https://www.ag-grid.com/ag-grid-typescript-webpack-2/)
[VueJS](https://www.ag-grid.com/best-vuejs-data-grid/) | [Web Components](https://www.ag-grid.com/best-web-component-data-grid/)
There are two examples:
@@ -18,5 +25,5 @@ Building
To build:
- `npm install`
- `npm install webpack -g`
- `npm run standard` or `npm run large`
- `npm run examples`, `npm run large` or `npm run trader`
- navigate to localhost:8080

26
gulpfile.js Normal file
View File

@@ -0,0 +1,26 @@
const gulp = require('gulp');
const gulpTypescript = require('gulp-typescript');
const merge = require('merge2');
gulp.task('watch', watchTask);
gulp.task('rebuild-ag-grid-react', rebuildAgGridReact);
const tsConfig = '../ag-grid-react/tsconfig.json';
const tsProject = gulpTypescript.createProject(tsConfig);
function rebuildAgGridReact() {
const tsResult = gulp
.src('../ag-grid-react/src/**/*.ts')
.pipe(tsProject());
return merge([
tsResult.dts
.pipe(gulp.dest('node_modules/ag-grid-react/lib')),
tsResult.js
.pipe(gulp.dest('node_modules/ag-grid-react/lib'))
]);
}
function watchTask() {
gulp.watch(['../ag-grid-react/src/**/*'], rebuildAgGridReact);
}

View File

@@ -1,6 +1,6 @@
{
"name": "ag-grid-react-example",
"version": "11.0.0",
"version": "13.3.0",
"description": "Example Reach applicaiton using ag-Grid.",
"main": "dist/ag-grid-react-example.js",
"scripts": {
@@ -12,17 +12,18 @@
"copy-examples": "ncp images dist/examples/images && ncp src/index.html dist/examples/index.html && ncp dist/react-examples.js dist/examples/dist/react-examples.js && ncp src dist/examples/src",
"copy-trader": "ncp src-trader-dashboard/index.html dist/trader/index.html && ncp dist/react-trader.js dist/trader/dist/react-trader.js",
"copy": "npm run copy-examples && npm run copy-trader",
"build-large": "webpack --config webpack.config.large.js --progress --profile --bail",
"build-examples": "webpack --config webpack.config.examples.js --progress --profile --bail",
"build-dashboard": "webpack --config webpack.config.trader.js --progress --profile --bail",
"build-all": "npm run build-examples && npm run build-dashboard",
"build": "npm run clean && npm run mkdirs && npm run build-all && npm run copy",
"copy-to-docs": "ncp dist/examples ../ag-grid-docs/src/react-examples/examples && ncp dist/trader ../ag-grid-docs/src/react-examples/trader",
"copy-to-docs": "ncp dist/examples ../ag-grid-docs/src/framework-examples/react-examples/examples && ncp dist/trader ../ag-grid-docs/src/framework-examples/react-examples/trader",
"build-to-docs": "npm run build && npm run copy-to-docs",
"start": "npm run examples"
},
"repository": {
"type": "git",
"url": "https://github.com/ceolter/ag-grid-react-example.git"
"url": "https://github.com/ag-grid/ag-grid-react-example.git"
},
"keywords": [
"react",
@@ -33,7 +34,7 @@
"author": "Niall Crosby <niall.crosby@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/ceolter/ag-grid-react-example/issues"
"url": "https://github.com/ag-grid/ag-grid-react-example/issues"
},
"homepage": "http://www.ag-grid.com/",
"devDependencies": {
@@ -43,29 +44,33 @@
"babel-preset-react": "6.24.x",
"babel-preset-stage-0": "6.24.x",
"babel-preset-stage-1": "6.24.x",
"prop-types": "15.5.x",
"css-loader": "0.23.x",
"mkdirp": "0.5.1",
"ncp": "2.0.0",
"prop-types": "15.5.x",
"rimraf": "2.5.x",
"style-loader": "0.13.x",
"webpack": "1.12.x",
"webpack-dev-server": "1.14.x"
"webpack-dev-server": "1.14.x",
"gulp": "3.9.x",
"gulp-typescript": "3.1.x",
"merge2": "1.0.x",
"typescript": "2.3.x"
},
"dependencies": {
"ag-grid": "13.3.x",
"ag-grid-enterprise": "13.3.x",
"ag-grid-react": "13.3.x",
"bootstrap": "3.3.7",
"d3": "4.9.1",
"file-loader": "0.11.1",
"lodash": "4.17.4",
"react": "15.5.x",
"react-dom": "15.5.x",
"react": "15.6.x",
"react-dom": "15.6.x",
"react-dom-factories": "1.0.0",
"react-redux": "5.0.x",
"react-router-dom": "4.2.x",
"redux": "3.6.x",
"url-search-params-polyfill": "1.2.0",
"ag-grid": "11.0.x",
"ag-grid-enterprise": "11.0.x",
"ag-grid-react": "11.0.x"
"url-search-params-polyfill": "1.2.0"
}
}

View File

@@ -23,21 +23,21 @@ export default class extends Component {
{
field: 'price',
headerName: 'Price',
cellFormatter: this.numberFormatter,
valueFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
cellStyle: {'text-align': 'right'}
},
{
field: 'bid',
headerName: 'Bid',
cellFormatter: this.numberFormatter,
valueFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
cellStyle: {'text-align': 'right'}
},
{
field: 'ask',
headerName: 'Ask',
cellFormatter: this.numberFormatter,
valueFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
cellStyle: {'text-align': 'right'}
}

View File

@@ -34,7 +34,7 @@ class TopMoversGrid extends Component {
cellRenderer: 'animateShowChange',
cellClass: 'align-right',
sort: 'desc',
cellFormatter(params) {
valueFormatter(params) {
return params.value.toFixed(2)
}
},

View File

@@ -3,6 +3,14 @@ import * as PropTypes from 'prop-types';
export default class HorizontalBarComponent extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value
}
}
render() {
let positiveChange = {
fill: "green"
@@ -19,7 +27,7 @@ export default class HorizontalBarComponent extends Component {
textAlign: "right"
};
let pctNetChange = this.props.value;
let pctNetChange = this.state.value;
let pctNetChangeBar = Math.min(Math.abs(pctNetChange) * 100, 100) / 2;
let barWidth = `${pctNetChangeBar}%`;
@@ -36,6 +44,13 @@ export default class HorizontalBarComponent extends Component {
</div>
)
}
refresh(params) {
this.setState({
value: params.value
});
return true;
}
}
HorizontalBarComponent.propTypes = {

View File

@@ -1,18 +1,70 @@
import React, {Component} from "react";
import {Redirect, Route, Switch} from "react-router-dom";
import "url-search-params-polyfill";
import NavItem from "./NavItem";
import DynamicComponentsExample from "./dynamicComponentExample/DynamicComponentsExample";
import RichGridExample from "./richGridExample/RichGridExample";
import RichComponentsExample from "./richComponentExample/RichComponentsExample";
import EditorComponentsExample from "./editorComponentExample/EditorComponentsExample";
import FloatingRowComponentExample from "./floatingRowExample/FloatingRowComponentExample";
import PinnedRowComponentExample from "./pinnedRowExample/PinnedRowComponentExample";
import FullWidthComponentExample from "./fullWidthExample/FullWidthComponentExample";
import GroupedRowInnerRendererComponentExample from "./groupedRowInnerRendererExample/GroupedRowInnerRendererComponentExample";
import FilterComponentExample from "./filterComponentExample/FilterComponentExample";
import MasterDetailExample from "./masterDetailExample/MasterDetailExample";
import SimpleReduxExample from "./simpleReduxExample/SimpleReduxExample";
import FloatingFilterGridExample from "./floatingFilter/FloatingFilterGridExample";
import SimpleReduxDynamicExample from "./simpleReduxDynamicComponentExample/SimpleReduxExample";
const SideBar = () => (
<div style={{float: "left", width: 335, marginRight: 25}}>
<ul className="nav nav-pills nav-stacked">
<NavItem to='/rich-grid'>Rich Grid Example</NavItem>
<NavItem to='/dynamic'>Dynamic React Component Example</NavItem>
<NavItem to='/rich-dynamic'>Dynamic React Components - Richer Example</NavItem>
<NavItem to='/editor'>Cell Editor Component Example</NavItem>
<NavItem to='/floating-row'>Floating Row Renderer Example</NavItem>
<NavItem to='/full-width'>Full Width Renderer Example</NavItem>
<NavItem to='/group-row'>Grouped Row Inner Renderer Example</NavItem>
<NavItem to='/filter'>Filters Component Example</NavItem>
<NavItem to='/master-detail'>Master Detail Example</NavItem>
<NavItem to='/floating-filter'>Floating Filters</NavItem>
<NavItem to='/simple-redux'>Simple Redux Example</NavItem>
<NavItem to='/simple-redux-dynamic'>Simple Redux Dynamic Component Example</NavItem>
</ul>
</div>
);
class App extends Component {
render() {
return (
<div style={{display: "inline-block", width: "100%"}}>
<SideBar/>
<div style={{float: "left"}}>
<Switch>
<Redirect from="/" exact to="/rich-grid"/>
<Route exact path='/rich-grid' component={RichGridExample}/>
<Route exact path='/dynamic' component={DynamicComponentsExample}/>
<Route exact path='/rich-dynamic' component={RichComponentsExample}/>
<Route exact path='/editor' component={EditorComponentsExample}/>
<Route exact path='/floating-row' component={PinnedRowComponentExample}/>
<Route exact path='/full-width' component={FullWidthComponentExample}/>
<Route exact path='/group-row' component={GroupedRowInnerRendererComponentExample}/>
<Route exact path='/filter' component={FilterComponentExample}/>
<Route exact path='/master-detail' component={MasterDetailExample}/>
<Route exact path='/floating-filter' component={FloatingFilterGridExample}/>
<Route exact path='/simple-redux' component={SimpleReduxExample}/>
<Route exact path='/simple-redux-dynamic' component={SimpleReduxDynamicExample}/>
</Switch>
</div>
</div>
)
}
}
export default App
/*
class App extends Component {
constructor(props) {
super(props);
@@ -44,12 +96,14 @@ class App extends Component {
<li role="presentation" className={this.state.example === 'dynamic' ? 'active' : null} onClick={() => this.setExample("dynamic")}><a href="#">Dynamic React Component Example</a></li>
<li role="presentation" className={this.state.example === 'rich-dynamic' ? 'active' : null} onClick={() => this.setExample("rich-dynamic")}><a href="#">Dynamic React Components - Richer Example</a></li>
<li role="presentation" className={this.state.example === 'editor' ? 'active' : null} onClick={() => this.setExample("editor")}><a href="#">Cell Editor Component Example</a></li>
<li role="presentation" className={this.state.example === 'floating-row' ? 'active' : null} onClick={() => this.setExample("floating-row")}><a href="#">Floating Row Renderer Example</a></li>
<li role="presentation" className={this.state.example === 'pinned-row' ? 'active' : null} onClick={() => this.setExample("pinned-row")}><a href="#">Pinned Row Renderer Example</a></li>
<li role="presentation" className={this.state.example === 'full-width' ? 'active' : null} onClick={() => this.setExample("full-width")}><a href="#">Full Width Renderer Example</a></li>
<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 === 'floating-filter' ? 'active' : null} onClick={() => this.setExample("floating-filter")}><a href="#">Floating Filters</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>
<li role="presentation" className={this.state.example === 'simple-redux-dynamic' ? 'active' : null} onClick={() => this.setExample("simple-redux-dynamic")}><a href="#">Simple Redux Dynamic Component Example</a></li>
</ul>)
}
@@ -64,8 +118,8 @@ class App extends Component {
case 'editor':
example = <EditorComponentsExample/>;
break;
case 'floating-row':
example = <FloatingRowComponentExample/>;
case 'pinned-row':
example = <PinnedRowComponentExample/>;
break;
case 'full-width':
example = <FullWidthComponentExample/>;
@@ -82,6 +136,12 @@ class App extends Component {
case 'simple-redux':
example = <SimpleReduxExample/>;
break;
case 'floating-filter':
example = <FloatingFilterGridExample/>;
break;
case 'simple-redux-dynamic':
example = <SimpleReduxDynamicExample/>;
break;
default:
example = <RichGridExample/>;
}
@@ -96,3 +156,4 @@ class App extends Component {
}
export default App
*/

19
src/NavItem.jsx Normal file
View File

@@ -0,0 +1,19 @@
import React, {PropTypes} from 'react'
import {Route, Link} from 'react-router-dom'
// for bootstrap li active functionality
export default function NavItem({children, to, exact}) {
return (
<Route path={to} exact={exact} children={({match}) => (
<li className={match ? 'active' : null}>
<Link to={to}>{children}</Link>
</li>
)}/>
)
}
NavItem.propTypes = {
to: PropTypes.string.isRequired,
exact: PropTypes.bool,
children: PropTypes.node.isRequired,
};

View File

@@ -13,7 +13,7 @@ export default class ChildMessageRenderer extends Component {
render() {
return (
<span><button style={{height: 20}} onClick={this.invokeParentMethod}>Invoke Parent</button></span>
<span><button style={{height: 20, lineHeight: 0.5}} onClick={this.invokeParentMethod} className="btn btn-info">Invoke Parent</button></span>
);
}
};

View File

@@ -3,15 +3,29 @@ import React, {Component} from "react";
export default class CurrencyRenderer extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
}
formatValueToCurrency(currency, value) {
return `${currency}${value}`
}
// noinspection JSUnusedGlobalSymbols
refresh(params) {
if(params.value !== this.state.value) {
this.setState({
value: params.value.toFixed(2)
})
}
return true;
}
render() {
return (
<span>{this.formatValueToCurrency('EUR', this.props.value)}</span>
<span>{this.formatValueToCurrency('EUR', this.state.value)}</span>
);
}
};

View File

@@ -18,13 +18,13 @@ export default class DynamicComponentsExample extends Component {
}
},
rowData: this.createRowData(),
rowData: DynamicComponentsExample.createRowData(),
columnDefs: this.createColumnDefs()
columnDefs: DynamicComponentsExample.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
this.refreshRowData = this.refreshRowData.bind(this);
this.refreshEvenRowsCurrencyData = this.refreshEvenRowsCurrencyData.bind(this);
}
onGridReady(params) {
@@ -34,22 +34,30 @@ export default class DynamicComponentsExample extends Component {
this.gridApi.sizeColumnsToFit();
}
onCellValueChanged($event) {
this.gridApi.refreshCells([$event.node],["cube"]);
}
methodFromParent(cell) {
alert(`Parent Component Method from ${cell}!`);
}
createColumnDefs() {
refreshEvenRowsCurrencyData() {
this.gridApi.forEachNode(rowNode => {
if (rowNode.data.value % 2 === 0) {
rowNode.setDataValue('currency', rowNode.data.value + Number(Math.random().toFixed(2)))
}
});
this.gridApi.refreshCells({
columns: ['currency']
})
}
static createColumnDefs() {
return [
{headerName: "Row", field: "row", width: 100},
{
headerName: "Square",
field: "value",
cellRendererFramework: SquareRenderer,
editable:true,
editable: true,
colId: "square",
width: 100
},
@@ -71,7 +79,7 @@ export default class DynamicComponentsExample extends Component {
headerName: "Currency",
field: "currency",
cellRendererFramework: CurrencyRenderer,
colId: "params",
colId: "currency",
width: 135
},
{
@@ -84,12 +92,7 @@ export default class DynamicComponentsExample extends Component {
];
}
refreshRowData() {
let rowData = this.createRowData();
this.gridApi.setRowData(rowData);
}
createRowData() {
static createRowData() {
let rowData = [];
for (let i = 0; i < 15; i++) {
@@ -102,12 +105,13 @@ export default class DynamicComponentsExample extends Component {
return rowData;
}
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Dynamic React Component Example</h1>
<button onClick={this.refreshRowData}>Refresh Data</button>
<button onClick={this.refreshEvenRowsCurrencyData} style={{marginBottom: 10}} className="btn btn-primary">Refresh Even Row Currency Data</button>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
@@ -117,6 +121,32 @@ export default class DynamicComponentsExample extends Component {
// events
onGridReady={this.onGridReady}>
</AgGridReact>
<div className="row">
<div className="col-sm-12"><h1>Dynamic React Component Example</h1></div>
</div>
<div className="row">
<div className="col-sm-12">
<h5>This example demonstrates Dynamic React Components with ag-Grid, Parent/Child Communication (cell component to parent grid component), as well as
dynamic data updates of the <code>Currency</code> column.</h5>
<p><span style={{fontWeight: "bold"}}>Square, Cube, Row Params, Currency and Child/Parent</span>: React Components within the Grid</p>
<p><span style={{fontWeight: "bold"}}>Currency (Pipe)</span>: An React Component mimicking a Currency Pipe, dynamically updated with the button above.</p>
<p><span style={{fontWeight: "bold"}}>Child/Parent</span>: Demonstrates the Child Cell Component communicating with the Parent Grid Component.</p>
<p><span style={{fontWeight: "bold"}}>Refresh Even Row Currency Data</span>: Dynamically Updates Event Rows Currency Value. Only the Currency column will be re-rendered.</p>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<h4 className="card-title">React Functionality</h4>
<p className="card-text">Utilise React Components within ag-Grid</p>
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-rendering-components/?framework=react" className="btn btn-primary">React Renderers</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-data-update/" className="btn btn-primary">Updating Data</a>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -10,8 +10,8 @@ export default class EditorComponentsExample extends Component {
super(props);
this.state = {
rowData: this.createRowData(),
columnDefs: this.createColumnDefs()
rowData: EditorComponentsExample.createRowData(),
columnDefs: EditorComponentsExample.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
@@ -24,9 +24,32 @@ export default class EditorComponentsExample extends Component {
this.gridApi.sizeColumnsToFit();
}
createColumnDefs() {
static createColumnDefs() {
return [
{headerName: "Name", field: "name", width: 300},
{
headerName: "Name",
field: "name",
width: 300,
editable: true,
cellEditor: 'richSelect',
cellEditorParams: {
values: [
"Bob",
"Harry",
"Sally",
"Mary",
"John",
"Jack",
"Sue",
"Sean",
"Niall",
"Albert",
"Fred",
"Jenny",
"Larry"
]
}
},
{
headerName: "Mood",
field: "mood",
@@ -45,7 +68,7 @@ export default class EditorComponentsExample extends Component {
];
}
createRowData() {
static createRowData() {
return [
{name: "Bob", mood: "Happy", number: 10},
{name: "Harry", mood: "Sad", number: 3},
@@ -65,7 +88,7 @@ export default class EditorComponentsExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 370, width: 900}}
className="ag-fresh">
<h1>Cell Editor Component Example</h1>
<AgGridReact
@@ -76,7 +99,34 @@ export default class EditorComponentsExample extends Component {
// events
onGridReady={this.onGridReady}>
</AgGridReact>
<div className="row">
<div className="col-sm-12"><h1>Cell Editor Component Example</h1></div>
</div>
<div className="row">
<div className="col-sm-12">
<h5>This example demonstrates React Editor Components within ag-Grid, as well as an example using the built in Rich Select editor.</h5>
<p><span style={{fontWeight: "bold"}}>Name</span>: Utilises the built in <code>RichSelect</code> editor</p>
<p><span style={{fontWeight: "bold"}}>Mood</span>: A Custom React Editor demonstrating popup functionality, with full keyboard control.</p>
<p><span style={{fontWeight: "bold"}}>Numeric</span>: A Custom React Editor demonstrating pre & post validation. Only numeric characters are allowed,
and numbers greater than 1000000 will be rejected.</p>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<h4 className="card-title">React Functionality</h4>
<p className="card-text">Utilise React Components within ag-Grid</p>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editing/?framework=react" className="btn btn-primary">Cell Editing</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react" className="btn btn-primary">Editor Components</a>
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react#reactCellEditing" className="btn btn-primary">React Editor Components</a>
</div>
</div>
</div>
</div>
</div>
);
}
};

View File

@@ -18,9 +18,21 @@ export default class MoodEditor extends Component {
}
componentDidMount() {
this.refs.container.addEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
this.focus();
}
componentWillUnmount() {
this.refs.container.removeEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
}
checkAndToggleMoodIfLeftRight = (event) => {
if ([37, 39].indexOf(event.keyCode) > -1) { // left and right
this.toggleMood();
event.stopPropagation();
}
}
componentDidUpdate() {
this.focus();
}
@@ -75,12 +87,11 @@ export default class MoodEditor extends Component {
background: "#e6e6e6",
padding: 15,
textAlign: "center",
display: "inline-block",
// outline: "none"
display: "inline-block"
};
let unselected = {
paddingLleft: 10,
paddingLeft: 10,
paddingRight: 10,
border: "1px solid transparent",
padding: 4
@@ -93,12 +104,14 @@ export default class MoodEditor extends Component {
padding: 4
};
let happyStyle = this.state.value === 'Happy' ? selected : unselected;
let sadStyle = this.state.value !== 'Happy' ? selected : unselected;
let happyStyle = this.state.happy ? selected : unselected;
let sadStyle = !this.state.happy ? selected : unselected;
return (
<div ref="container"
style={mood}>
style={mood}
tabIndex={1} // important - without this the keypresses wont be caught
>
<img src="images/smiley.png" onClick={this.onHappyClick} style={happyStyle}/>
<img src="images/smiley-sad.png" onClick={this.onSadClick} style={sadStyle}/>
</div>

View File

@@ -1,21 +1,25 @@
import React, {Component} from "react";
import ReactDOM from "react-dom";
export default class MoodEditor extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value
};
this.cancelBeforeStart = this.props.charPress && ('1234567890'.indexOf(this.props.charPress) < 0);
let value = this.props.value;
if (!this.cancelBeforeStart && this.props.charPress) {
value = value + this.props.charPress;
}
this.state = {
value
};
this.onKeyDown = this.onKeyDown.bind(this);
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
this.refs.input.addEventListener('keydown', this.onKeyDown);
this.focus();
}
@@ -23,12 +27,15 @@ export default class MoodEditor extends Component {
this.focus();
}
componentWillUnmount() {
this.refs.input.removeEventListener('keydown', this.onKeyDown);
}
focus() {
setTimeout(() => {
let container = ReactDOM.findDOMNode(this.refs.input);
if (container) {
container.focus();
}
this.refs.input.focus();
this.refs.input.setSelectionRange(this.state.value.length, this.state.value.length);
})
}
@@ -47,11 +54,20 @@ export default class MoodEditor extends Component {
};
onKeyDown(event) {
if (this.isLeftOrRight(event)) {
event.stopPropagation();
return;
}
if (!this.isKeyPressedNumeric(event)) {
if (event.preventDefault) event.preventDefault();
}
}
isLeftOrRight(event) {
return [37, 39].indexOf(event.keyCode) > -1;
}
handleChange(event) {
this.setState({value: event.target.value});
}
@@ -75,8 +91,8 @@ export default class MoodEditor extends Component {
return (
<input ref="input"
value={this.state.value}
onKeyDown={this.onKeyDown}
onChange={this.handleChange}
style={{width: "100%"}}
/>
);
}

View File

@@ -13,8 +13,8 @@ export default class FilterComponentExample extends Component {
this.state = {
gridOptions: {},
rowData: this.createRowData(),
columnDefs: this.createColumnDefs(),
rowData: FilterComponentExample.createRowData(),
columnDefs: FilterComponentExample.createColumnDefs(),
};
this.onGridReady = this.onGridReady.bind(this);
@@ -32,7 +32,7 @@ export default class FilterComponentExample extends Component {
this.gridApi.getFilterInstance("name").getFrameworkComponentInstance().componentMethod("Hello World!");
}
createColumnDefs() {
static createColumnDefs() {
return [
{headerName: "Row", field: "row", width: 400},
{
@@ -45,7 +45,7 @@ export default class FilterComponentExample extends Component {
];
}
createRowData() {
static createRowData() {
return [
{"row": "Row 1", "name": "Michael Phelps"},
{"row": "Row 2", "name": "Natalie Coughlin"},
@@ -66,10 +66,10 @@ export default class FilterComponentExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Filter Component Example</h1>
<button style={{marginBottom: 10}} onClick={this.onClicked}>Filter Instance Method</button>
<button style={{marginBottom: 10}} onClick={this.onClicked} className="btn btn-primary">Filter Instance Method</button>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}

View File

@@ -7,7 +7,8 @@ export default class PartialMatchFilter extends Component {
this.state = {
text: ''
}
};
this.valueGetter = this.props.valueGetter;
this.onChange = this.onChange.bind(this);
@@ -63,8 +64,17 @@ export default class PartialMatchFilter extends Component {
}
render() {
let style = {
border: "2px solid #22ff22",
borderRadius: "5px",
backgroundColor: "#bbffbb",
width: "200px",
height: "50px"
};
return (
<span>Filter: <input style={{height: "20px"}} ref="input" value={this.state.text} onChange={this.onChange}/></span>
<div style={style}>Filter: <input style={{height: "20px"}} ref="input" value={this.state.text}
onChange={this.onChange} className="form-control"/></div>
);
}
};

View File

@@ -0,0 +1,69 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import FloatingFilter from "./floatingFilter";
import overrideStyle from "./floatingFilter.css";
export default class FloatingFilterGridExample extends Component {
constructor(props) {
super(props);
this.state = {
columnDefs: this.createColumnDefs(),
rowData: this.createRowData()
}
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
createColumnDefs() {
return [
{
headerName: "Make",
field: "make",
floatingFilterComponentFramework: FloatingFilter,
filter: 'set'
},
{headerName: "Model", field: "model"},
{headerName: "Price", field: "price"}
];
}
createRowData() {
return [
{make: "Toyota", model: "Celica", price: 35000},
{make: "Ford", model: "Mondeo", price: 32000},
{make: "Porsche", model: "Boxter", price: 72000}
];
}
render() {
let divStyle = {
height: 400,
width: 900
};
// combine the styles
const style = Object.assign({}, divStyle, overrideStyle);
return (
<div style={style} className="ag-fresh">
<h1>Floating Filter Example</h1>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
floatingFilter={true}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
)
}
};

View File

@@ -0,0 +1,3 @@
.ag-floating-filter-button button {
margin: 0
}

View File

@@ -0,0 +1,39 @@
import React, {Component} from "react";
export default class FloatingFilter extends Component {
constructor(props) {
super(props);
this.state = {
parentModel: null
}
}
// when does this get called? how to test this?
onParentModelChanged(parentModel) {
this.setState({
parentModel: parentModel
})
}
remove(item) {
this.props.onFloatingFilterChanged({
model: this.state.parentModel.filter(it => it !== item)
});
}
render() {
if (!this.state.parentModel) return null;
// as the backing filter is a set filter what we're doing here is rendering the list in the set
// and when the [x] removing the selected item, thereby effectively hiding it
let options = this.state.parentModel.map((item, i) => {
let removeMeListener = () => {
this.remove(item)
};
let removeMeElement = <a onClick={removeMeListener}>[x]</a>;
return <span key={i}>{item}{removeMeElement}</span>;
});
return <div>{options}</div>;
}
}

View File

@@ -10,8 +10,8 @@ export default class FullWidthComponentExample extends Component {
this.state = {
gridOptions: {},
rowData: this.createRowData(),
columnDefs: this.createColumnDefs()
rowData: FullWidthComponentExample.createRowData(),
columnDefs: FullWidthComponentExample.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
@@ -28,7 +28,7 @@ export default class FullWidthComponentExample extends Component {
return (rowNode.id === "0") || (parseInt(rowNode.id) % 2 === 0);
}
createColumnDefs() {
static createColumnDefs() {
return [
{
headerName: "Name",
@@ -43,7 +43,7 @@ export default class FullWidthComponentExample extends Component {
];
}
createRowData() {
static createRowData() {
return [
{name: "Bob", age: 10},
{name: "Harry", age: 3},
@@ -68,7 +68,7 @@ export default class FullWidthComponentExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Full Width Renderer Example</h1>
<AgGridReact

View File

@@ -8,8 +8,14 @@ export default class NameAndAgeRenderer extends Component {
}
render() {
let style = {
border: "2px solid #22ff22",
borderRadius: "5px",
backgroundColor: "#bbffbb"
};
return (
<span>Full Width Column! { this.values }</span>
<div style={style}>Full Width Column! { this.values }</div>
);
}
};

View File

@@ -106,7 +106,7 @@ export default class GroupedRowInnerRendererComponentExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Group Row Renderer Example</h1>
<AgGridReact

View File

@@ -12,40 +12,51 @@
height: 100%;
}
body {
line-height: 1
}
div.card-body > a {
margin-top: 5px
}
.btn-primary {
margin-right: 5px;
}
button {
margin-left: 4px;
margin-right: 4px;
}
.align-right {
text-align: right
}
.customHeaderMenuButton {
margin-top: 5px;
margin-left: 4px;
float: left;
}
.customHeaderLabel {
margin-left: 5px;
margin-top: 3px;
float: left;
}
.customSortDownLabel {
float: left;
margin-left: 10px;
margin-top: 5px;
}
.customSortUpLabel {
float: left;
margin-left: 3px;
margin-top: 4px;
}
.customSortRemoveLabel {
float: left;
font-size: 11px;
margin-left: 3px;
margin-top: 6px;
}
.active {
@@ -58,21 +69,19 @@
.customHeaderLabel {
margin-left: 5px;
margin-top: 3px;
float: left;
}
.customExpandButton {
float: right;
margin-top: 5px;
margin-left: 3px;
}
.expanded {
animation-name: toExpanded;
animation-duration: 1s;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
@@ -80,22 +89,22 @@
color: cornflowerblue;
animation-name: toCollapsed;
animation-duration: 1s;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
@keyframes toExpanded {
from {
color: cornflowerblue;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
to {
color: black;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
}
@@ -103,14 +112,14 @@
@keyframes toCollapsed {
from {
color: black;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
to {
color: cornflowerblue;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
}
@@ -120,4 +129,4 @@
<body>
<div id="app"></div>
</body>
</html>
</html>

View File

@@ -2,6 +2,7 @@
import React from "react";
import {render} from "react-dom";
import {BrowserRouter} from "react-router-dom";
import "ag-grid-root/dist/styles/ag-grid.css";
import "ag-grid-root/dist/styles/theme-fresh.css";
@@ -9,9 +10,15 @@ import "../node_modules/bootstrap/dist/css/bootstrap.css";
import App from "./App";
// only required when using enterprise features
// import {LicenseManager} from "ag-grid-enterprise/main";
// LicenseManager.setLicenseKey("<your license key>");
document.addEventListener('DOMContentLoaded', () => {
render(
<App/>,
<BrowserRouter>
<App/>
</BrowserRouter>,
document.querySelector('#app')
);
});

View File

@@ -116,7 +116,7 @@ export default class MasterDetailExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Master-Detail Example</h1>
<AgGridReact

View File

@@ -3,7 +3,7 @@ import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import StyledRenderer from "./StyledRenderer";
export default class FloatingRowComponentExample extends Component {
export default class PinnedRowComponentExample extends Component {
constructor(props) {
super(props);
@@ -13,8 +13,8 @@ export default class FloatingRowComponentExample extends Component {
rowData: this.createRowData(),
columnDefs: this.createColumnDefs(),
topFloatingRowData: [{row: "Top Row", number: "Top Number"}],
bottomFloatingRowData: [{row: "Bottom Row", number: "Bottom Number"}]
pinnedTopRowData: [{row: "Top Row", number: "Top Number"}],
pinnedBottomRowData: [{row: "Bottom Row", number: "Bottom Number"}]
};
this.onGridReady = this.onGridReady.bind(this);
@@ -33,8 +33,8 @@ export default class FloatingRowComponentExample extends Component {
headerName: "Row",
field: "row",
width: 400,
floatingCellRendererFramework: StyledRenderer,
floatingCellRendererParams: {
pinnedRowCellRendererFramework: StyledRenderer,
pinnedRowCellRendererParams: {
style: {'fontWeight': 'bold'}
}
},
@@ -42,8 +42,8 @@ export default class FloatingRowComponentExample extends Component {
headerName: "Number",
field: "number",
width: 399,
floatingCellRendererFramework: StyledRenderer,
floatingCellRendererParams: {
pinnedRowCellRendererFramework: StyledRenderer,
pinnedRowCellRendererParams: {
style: {'fontStyle': 'italic'}
}
},
@@ -65,16 +65,16 @@ export default class FloatingRowComponentExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
<div style={{height: 400, width: 900}}
className="ag-fresh">
<h1>Floating Row Renderer Example</h1>
<h1>Pinned Row Renderer Example</h1>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
floatingTopRowData={this.state.topFloatingRowData}
floatingBottomRowData={this.state.bottomFloatingRowData}
pinnedTopRowData={this.state.pinnedTopRowData}
pinnedBottomRowData={this.state.pinnedBottomRowData}
// events
onGridReady={this.onGridReady}>

View File

@@ -20,7 +20,7 @@ export default class ClickableRenderer extends Component {
render() {
return (
<button style={{height: 21}} onClick={this.clicked} >Click Me</button>
<button style={{lineHeight: 0.5, width: "98%"}} onClick={this.clicked} className="btn btn-info">Click Me</button>
);
}
}

View File

@@ -9,8 +9,8 @@ export default class RichComponentsExample extends Component {
super(props);
this.state = {
rowData: this.createRowData(),
columnDefs: this.createColumnDefs()
rowData: RichComponentsExample.createRowData(),
columnDefs: RichComponentsExample.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
@@ -23,9 +23,13 @@ export default class RichComponentsExample extends Component {
this.gridApi.sizeColumnsToFit();
}
createColumnDefs() {
static createColumnDefs() {
return [
{headerName: "Name", field: "name", width: 200},
{
headerName: "Name",
field: "name",
width: 200
},
{
headerName: "Ratio Component",
field: "ratios",
@@ -40,7 +44,7 @@ export default class RichComponentsExample extends Component {
}
]; }
createRowData() {
static createRowData() {
return [
{name: 'Homer Simpson', ratios: {top: 0.25, bottom: 0.75}},
{name: 'Marge Simpson', ratios: {top: 0.67, bottom: 0.39}},
@@ -60,8 +64,7 @@ export default class RichComponentsExample extends Component {
render() {
return (
<div style={{height: 400, width: 945}}
className="ag-fresh">
<div style={{height: 370, width: 900}} className="ag-fresh">
<h1>Dynamic React Components - Richer Example</h1>
<AgGridReact
// properties
@@ -72,6 +75,24 @@ export default class RichComponentsExample extends Component {
// events
onGridReady={this.onGridReady}>
</AgGridReact>
<div className="row">
<div className="col-sm-12">
<h5>This example demonstrates Dynamic React Components with ag-Grid. Functionally similar
to the <a href="/dynamic">Dynamic React Components Example</a> but with slightly richer components.</h5>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<h4 className="card-title">React Functionality</h4>
<p className="card-text">Utilise React Components within ag-Grid</p>
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-rendering-components/?framework=react" className="btn btn-primary">React Renderers</a>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -9,46 +9,82 @@ import HeaderGroupComponent from './HeaderGroupComponent.jsx';
export default class ColDefFactory {
createColDefs() {
var columnDefs = [
{headerName: '#', width: 30, checkboxSelection: true, suppressSorting: true,
suppressMenu: true, pinned: true},
return [
{
headerName: '#',
width: 30,
checkboxSelection: true,
suppressSorting: true,
suppressMenu: true,
suppressFilter: true,
pinned: true
},
{
headerName: 'Employee',
headerGroupComponentFramework: HeaderGroupComponent,
children: [
{
headerName: "Name", field: "name", enableRowGroup: true, enablePivot: true,
width: 150, pinned: true, editable: true,
headerName: "Name",
field: "name",
enableRowGroup: true,
enablePivot: true,
width: 150,
pinned: true,
editable: true,
// use a React cellEditor
cellEditorFramework: NameCellEditor
}, {
headerName: "Country", field: "country", width: 150, enableRowGroup: true, enablePivot: true,
},
{
headerName: "Country",
field: "country",
width: 150,
enableRowGroup: true,
enablePivot: true,
// an example of using a non-React cell renderer
cellRenderer: countryCellRenderer, pinned: true,
cellRenderer: countryCellRenderer,
pinned: true,
filterParams: {
cellRenderer: countryCellRenderer, cellHeight: 20
}, columnGroupShow: 'open'
}, {
headerName: "DOB", field: "dob", width: 110, enableRowGroup: true, enablePivot: true, filter:'date',
pinned: true, cellRenderer: function(params) {
return pad(params.value.getDate(), 2) + '/' +
pad(params.value.getMonth() + 1, 2)+ '/' +
params.value.getFullYear();
}, columnGroupShow: 'open'
cellRenderer: countryCellRenderer,
cellHeight: 20
}
},
{
headerName: "DOB",
field: "dob",
width: 110,
enableRowGroup: true,
enablePivot: true,
filter: 'date',
pinned: true,
cellRenderer: function (params) {
return pad(params.value.getDate(), 2) + '/' +
pad(params.value.getMonth() + 1, 2) + '/' +
params.value.getFullYear();
},
columnGroupShow: 'open'
}
]
},
{
headerName: 'IT Skills',
children: [
{headerName: "Skills", width: 125, suppressSorting: true, field: 'skills', enableRowGroup: true, enablePivot: true,
{
headerName: "Skills",
width: 125,
suppressSorting: true,
field: 'skills',
enableRowGroup: true,
enablePivot: true,
// supply a React component
cellRendererFramework: SkillsCellRenderer,
// supply a React component
filterFramework: SkillsFilter
},
{headerName: "Proficiency", field: "proficiency", width: 135, enableValue: true,
{
headerName: "Proficiency",
field: "proficiency",
width: 135,
enableValue: true,
// supply a React component
cellRendererFramework: ProficiencyCellRenderer,
// supply a React component
@@ -65,7 +101,6 @@ export default class ColDefFactory {
]
}
];
return columnDefs;
}
}
@@ -73,7 +108,7 @@ export default class ColDefFactory {
// need to use React for it.
function countryCellRenderer(params) {
if (params.value) {
var flag = "<img border='0' width='15' height='10' " +
const flag = "<img border='0' width='15' height='10' " +
"style='margin-bottom: 2px' src='http://flags.fmcdn.net/data/flags/mini/"
+ RefData.COUNTRY_CODES[params.value] + ".png'>";
return flag + " " + params.value;

View File

@@ -17,19 +17,20 @@ export default class HeaderGroupComponent extends React.Component {
}
render() {
let arrowClassName = "customExpandButton " + (this.state.expanded ? " expanded": " collapsed");
let arrowClassName = "customExpandButton " + (this.state.expanded ? " expanded" : " collapsed");
return <div>
<div className="customHeaderLabel"> {this.props.displayName}</div>
<div onClick={this.expandOrCollapse.bind(this)} className={arrowClassName}><i className="fa fa-arrow-right" /></div>
<div onClick={this.expandOrCollapse.bind(this)} className={arrowClassName}><i
className="fa fa-arrow-right"/></div>
</div>
}
expandOrCollapse (){
expandOrCollapse() {
this.props.setExpanded(!this.state.expanded);
};
onExpandChanged (){
onExpandChanged() {
this.setState({
expanded: this.props.columnGroup.getOriginalColumnGroup().isExpanded()
})

View File

@@ -1,10 +1,9 @@
import React from 'react';
import RefData from './RefData';
import * as PropTypes from 'prop-types';
var KEY_BACKSPACE = 8;
var KEY_DELETE = 46;
var KEY_F2 = 113;
const KEY_BACKSPACE = 8;
const KEY_DELETE = 46;
const KEY_F2 = 113;
// cell renderer for the proficiency column. this is a very basic cell editor,
export default class NameCellEditor extends React.Component {
@@ -20,9 +19,9 @@ export default class NameCellEditor extends React.Component {
// experience is similar to Excel
createInitialState(props) {
var startValue;
var putCursorAtEndOnFocus = false;
var highlightAllOnFocus = false;
let startValue;
const putCursorAtEndOnFocus = false;
const highlightAllOnFocus = false;
if (props.keyPress === KEY_BACKSPACE || props.keyPress === KEY_DELETE) {
// if backspace or delete pressed, we clear the cell
@@ -56,7 +55,7 @@ export default class NameCellEditor extends React.Component {
onChangeListener(event) {
// if doing React, you will probably be using a library for managing immutable
// objects better. to keep this example simple, we don't use one.
var newState = {
const newState = {
value: event.target.value,
putCursorAtEndOnFocus: this.state.putCursorAtEndOnFocus,
highlightAllOnFocus: this.state.highlightAllOnFocus
@@ -73,7 +72,7 @@ export default class NameCellEditor extends React.Component {
// view, it may not yet be in the browser (put in by ag-Grid) so focus will not work
afterGuiAttached() {
// get ref from React component
var eInput = this.refs.textField;
const eInput = this.refs.textField;
eInput.focus();
if (this.highlightAllOnFocus) {
eInput.select();
@@ -82,7 +81,7 @@ export default class NameCellEditor extends React.Component {
// this comes into play in two scenarios: a) when user hits F2 and b)
// when user hits a printable character, then on IE (and only IE) the carot
// was placed after the first character, thus 'apply' would end up as 'pplea'
var length = eInput.value ? eInput.value.length : 0;
const length = eInput.value ? eInput.value.length : 0;
if (length > 0) {
eInput.setSelectionRange(length, length);
}
@@ -101,7 +100,7 @@ export default class NameCellEditor extends React.Component {
// just to demonstrate, if you type in 'cancel' then the edit will not take effect
isCancelAfterEnd() {
if (this.state.value && this.state.value.toUpperCase()==='CANCEL') {
if (this.state.value && this.state.value.toUpperCase() === 'CANCEL') {
return true;
} else {
return false;

View File

@@ -1,5 +1,4 @@
import React from 'react';
import RefData from './RefData';
// cell renderer for the proficiency column. this is a very basic cell renderer,
// it is arguable that we should not of used React and just returned a string of
@@ -7,7 +6,7 @@ import RefData from './RefData';
export default class ProficiencyCellRenderer extends React.Component {
render() {
var backgroundColor;
let backgroundColor;
if (this.props.value < 20) {
backgroundColor = 'red';
} else if (this.props.value < 60) {
@@ -17,7 +16,7 @@ export default class ProficiencyCellRenderer extends React.Component {
}
return (
<div className="div-percent-bar" style={{ width: this.props.value + '%', backgroundColor: backgroundColor }}>
<div className="div-percent-bar" style={{width: this.props.value + '%', backgroundColor: backgroundColor}}>
<div className="div-percent-value">{this.props.value}%</div>
</div>
);

View File

@@ -1,13 +1,13 @@
import React from 'react';
var PROFICIENCY_NAMES = ['No Filter', 'Above 40%', 'Above 60%', 'Above 80%'];
const PROFICIENCY_NAMES = ['No Filter', 'Above 40%', 'Above 60%', 'Above 80%'];
// the proficiency filter component. this demonstrates how to integrate
// a React filter component with ag-Grid.
export default class ProficiencyFilter extends React.Component {
constructor(props) {
super();
super(props);
this.state = {
selected: PROFICIENCY_NAMES[0]
};
@@ -15,14 +15,18 @@ export default class ProficiencyFilter extends React.Component {
// called by agGrid
doesFilterPass(params) {
var value = this.props.valueGetter(params);
var valueAsNumber = parseFloat(value);
const value = this.props.valueGetter(params);
const valueAsNumber = parseFloat(value);
switch (this.state.selected) {
case PROFICIENCY_NAMES[1] : return valueAsNumber >= 40;
case PROFICIENCY_NAMES[2] : return valueAsNumber >= 60;
case PROFICIENCY_NAMES[3] : return valueAsNumber >= 80;
default : return true;
case PROFICIENCY_NAMES[1] :
return valueAsNumber >= 40;
case PROFICIENCY_NAMES[2] :
return valueAsNumber >= 60;
case PROFICIENCY_NAMES[3] :
return valueAsNumber >= 80;
default :
return true;
}
};
@@ -32,19 +36,24 @@ export default class ProficiencyFilter extends React.Component {
};
onButtonPressed(name) {
var newState = {selected: name};
const newState = {selected: name};
// set the state, and once it is done, then call filterChangedCallback
this.setState(newState, this.props.filterChangedCallback);
}
getModel() {
return ''
}
render() {
var rows = [];
PROFICIENCY_NAMES.forEach( (name)=> {
var selected = this.state.selected === name;
const rows = [];
PROFICIENCY_NAMES.forEach((name) => {
const selected = this.state.selected === name;
rows.push(
<div key={name}>
<label style={{paddingLeft: 4}}>
<input type="radio" checked={selected} name={Math.random()} onChange={this.onButtonPressed.bind(this, name)}/>
<input type="radio" checked={selected} name={Math.random()}
onChange={this.onButtonPressed.bind(this, name)}/>
{name}
</label>
</div>
@@ -53,7 +62,13 @@ export default class ProficiencyFilter extends React.Component {
return (
<div>
<div style={{textAlign: 'center', background: 'lightgray', width: '100%', display: 'block', borderBottom: '1px solid grey'}}>
<div style={{
textAlign: 'center',
background: 'lightgray',
width: '100%',
display: 'block',
borderBottom: '1px solid grey'
}}>
<b>Custom Proficiency Filter</b>
</div>
{rows}

View File

@@ -1,127 +1,128 @@
export default class RefData {}
export default class RefData {
}
RefData.FIRST_NAMES = [
"Sophie", "Isabelle", "Emily", "Olivia", "Lily", "Chloe", "Isabella",
"Amelia", "Jessica", "Sophia", "Ava", "Charlotte", "Mia", "Lucy", "Grace", "Ruby",
"Ella", "Evie", "Freya", "Isla", "Poppy", "Daisy", "Layla"
];
"Sophie", "Isabelle", "Emily", "Olivia", "Lily", "Chloe", "Isabella",
"Amelia", "Jessica", "Sophia", "Ava", "Charlotte", "Mia", "Lucy", "Grace", "Ruby",
"Ella", "Evie", "Freya", "Isla", "Poppy", "Daisy", "Layla"
];
RefData.LAST_NAMES = [
"Beckham", "Black", "Braxton", "Brennan", "Brock", "Bryson", "Cadwell",
"Cage", "Carson", "Chandler", "Cohen", "Cole", "Corbin", "Dallas", "Dalton", "Dane",
"Donovan", "Easton", "Fisher", "Fletcher", "Grady", "Greyson", "Griffin", "Gunner",
"Hayden", "Hudson", "Hunter", "Jacoby", "Jagger", "Jaxon", "Jett", "Kade", "Kane",
"Keating", "Keegan", "Kingston", "Kobe"
];
"Beckham", "Black", "Braxton", "Brennan", "Brock", "Bryson", "Cadwell",
"Cage", "Carson", "Chandler", "Cohen", "Cole", "Corbin", "Dallas", "Dalton", "Dane",
"Donovan", "Easton", "Fisher", "Fletcher", "Grady", "Greyson", "Griffin", "Gunner",
"Hayden", "Hudson", "Hunter", "Jacoby", "Jagger", "Jaxon", "Jett", "Kade", "Kane",
"Keating", "Keegan", "Kingston", "Kobe"
];
RefData.COUNTRY_CODES = {
Ireland: "ie",
Spain: "es",
"United Kingdom": "gb",
France: "fr",
Germany: "de",
Sweden: "se",
Italy: "it",
Greece: "gr",
Iceland: "is",
Portugal: "pt",
Malta: "mt",
Norway: "no",
Brazil: "br",
Argentina: "ar",
Colombia: "co",
Peru: "pe",
Venezuela: "ve",
Uruguay: "uy"
};
Ireland: "ie",
Spain: "es",
"United Kingdom": "gb",
France: "fr",
Germany: "de",
Sweden: "se",
Italy: "it",
Greece: "gr",
Iceland: "is",
Portugal: "pt",
Malta: "mt",
Norway: "no",
Brazil: "br",
Argentina: "ar",
Colombia: "co",
Peru: "pe",
Venezuela: "ve",
Uruguay: "uy"
};
RefData.COUNTRIES = [
{country: "Ireland", continent: "Europe", language: "English"},
{country: "Spain", continent: "Europe", language: "Spanish"},
{country: "United Kingdom", continent: "Europe", language: "English"},
{country: "France", continent: "Europe", language: "French"},
{country: "Germany", continent: "Europe", language: "(other)"},
{country: "Sweden", continent: "Europe", language: "(other)"},
{country: "Norway", continent: "Europe", language: "(other)"},
{country: "Italy", continent: "Europe", language: "(other)"},
{country: "Greece", continent: "Europe", language: "(other)"},
{country: "Iceland", continent: "Europe", language: "(other)"},
{country: "Portugal", continent: "Europe", language: "Portuguese"},
{country: "Malta", continent: "Europe", language: "(other)"},
{country: "Brazil", continent: "South America", language: "Portuguese"},
{country: "Argentina", continent: "South America", language: "Spanish"},
{country: "Colombia", continent: "South America", language: "Spanish"},
{country: "Peru", continent: "South America", language: "Spanish"},
{country: "Venezuela", continent: "South America", language: "Spanish"},
{country: "Uruguay", continent: "South America", language: "Spanish"}
];
{country: "Ireland", continent: "Europe", language: "English"},
{country: "Spain", continent: "Europe", language: "Spanish"},
{country: "United Kingdom", continent: "Europe", language: "English"},
{country: "France", continent: "Europe", language: "French"},
{country: "Germany", continent: "Europe", language: "(other)"},
{country: "Sweden", continent: "Europe", language: "(other)"},
{country: "Norway", continent: "Europe", language: "(other)"},
{country: "Italy", continent: "Europe", language: "(other)"},
{country: "Greece", continent: "Europe", language: "(other)"},
{country: "Iceland", continent: "Europe", language: "(other)"},
{country: "Portugal", continent: "Europe", language: "Portuguese"},
{country: "Malta", continent: "Europe", language: "(other)"},
{country: "Brazil", continent: "South America", language: "Portuguese"},
{country: "Argentina", continent: "South America", language: "Spanish"},
{country: "Colombia", continent: "South America", language: "Spanish"},
{country: "Peru", continent: "South America", language: "Spanish"},
{country: "Venezuela", continent: "South America", language: "Spanish"},
{country: "Uruguay", continent: "South America", language: "Spanish"}
];
RefData.DOB = [
new Date(2000, 0, 1 ),
new Date(2001, 1, 2 ),
new Date(2002, 2, 3 ),
new Date(2003, 3, 4 ),
new Date(2004, 4, 5 ),
new Date(2005, 5, 6 ),
new Date(2006, 6, 7 ),
new Date(2007, 7, 8 ),
new Date(2008, 8, 9 ),
new Date(2009, 9, 10 ),
new Date(2010, 10, 11 ),
new Date(2011, 11, 12 )
new Date(2000, 0, 1),
new Date(2001, 1, 2),
new Date(2002, 2, 3),
new Date(2003, 3, 4),
new Date(2004, 4, 5),
new Date(2005, 5, 6),
new Date(2006, 6, 7),
new Date(2007, 7, 8),
new Date(2008, 8, 9),
new Date(2009, 9, 10),
new Date(2010, 10, 11),
new Date(2011, 11, 12)
];
RefData.ADDRESSES = [
'1197 Thunder Wagon Common, Cataract, RI, 02987-1016, US, (401) 747-0763',
'3685 Rocky Glade, Showtucket, NU, X1E-9I0, CA, (867) 371-4215',
'3235 High Forest, Glen Campbell, MS, 39035-6845, US, (601) 638-8186',
'2234 Sleepy Pony Mall , Drain, DC, 20078-4243, US, (202) 948-3634',
'2722 Hazy Turnabout, Burnt Cabins, NY, 14120-5642, US, (917) 604-6597',
'6686 Lazy Ledge, Two Rock, CA, 92639-3020, US, (619) 901-9911',
'2000 Dewy Limits, Wacahoota, NF, A4L-2V9, CA, (709) 065-3959',
'7710 Noble Pond Avenue, Bolivia, RI, 02931-1842, US, (401) 865-2160',
'3452 Sunny Vale, Pyro, ON, M8V-4Z0, CA, (519) 072-8609',
'4402 Dusty Cove, Many Farms, UT, 84853-8223, US, (435) 518-0673',
'5198 Silent Parade, Round Bottom, MD, 21542-9798, US, (301) 060-7245',
'8550 Shady Moor, Kitty Fork, CO, 80941-6207, US, (303) 502-3767',
'2131 Old Dell, Merry Midnight, AK, 99906-8842, US, (907) 369-2206',
'7390 Harvest Crest, Mosquito Crossing, RI, 02957-6116, US, (401) 463-6348',
'874 Little Point, Hot Coffee, BC, V3U-2P6, CA, (250) 706-9207',
'8834 Stony Pioneer Heights, Newlove, OR, 97419-8670, US, (541) 408-2213',
'9829 Grand Beach, Flint, UT, 84965-9900, US, (435) 700-5161',
'3799 Cozy Blossom Ramp, Ptarmigan, MS, 38715-0313, US, (769) 740-1526',
'3254 Silver Island Loop, Maunaloa, DE, 19869-3169, US, (302) 667-7671',
'1081 Middle Wood, Taylors Gut Landing, OR, 97266-2873, US, (541) 357-6310',
'1137 Umber Trail, Shacktown, NW, X3U-5Y8, CA, (867) 702-6883',
'9914 Hidden Bank, Wyoming, MO, 64635-9665, US, (636) 280-4192',
'7080 Misty Nectar Townline, Coward, AB, T9U-3N4, CA, (403) 623-2838',
'1184 Wishing Grounds, Vibank, NW, X7D-0V9, CA, (867) 531-2730',
'126 Easy Pointe, Grandview Beach, KY, 40928-9539, US, (502) 548-0956',
'6683 Colonial Street, Swan River, BC, V1A-9I8, CA, (778) 014-4257',
'960 Gentle Oak Lane, Shakopee, ND, 58618-6277, US, (701) 327-1219',
'6918 Cotton Pine Corner, Kenaston, IA, 52165-3975, US, (515) 906-7427',
'2368 Burning Woods, Ernfold, NY, 11879-9186, US, (646) 819-0355',
'5646 Quiet Shadow Chase, Tiger Tail, IA, 52283-5537, US, (712) 375-9225',
'5466 Foggy Mountain Dale, Sweet Home, MT, 59738-0251, US, (406) 881-1706',
'5313 Clear Willow Route, Amazon, BC, V0S-2S6, CA, (604) 340-7596',
'7000 Pleasant Autoroute, Spaceport City, UT, 84749-2448, US, (435) 154-3360',
'8359 Quaking Anchor Road, Gross, BC, V9O-0H5, CA, (250) 985-3859',
'5143 Amber Deer Hollow, New Deal, ND, 58446-0853, US, (701) 927-0322',
'6230 Jagged Bear Key, Young, AR, 72337-3811, US, (501) 805-7239',
'7207 Heather Vista, Devon, WY, 82520-1771, US, (307) 358-7092',
'9416 Red Rise Place, Spraytown, OK, 73809-4766, US, (580) 867-1973',
'3770 Golden Horse Diversion, Yelland, IL, 60471-1487, US, (224) 717-9349',
'4819 Honey Treasure Park, Alaska, NB, E1U-3I0, CA, (506) 656-9138',
'6187 Round Front, Land O Lakes, AK, 99873-6403, US, (907) 853-9063',
'9218 Crystal Highway, Pickelville, MT, 59847-9299, US, (406) 076-0024',
'6737 Bright Quay, Lazy Mountain, KY, 42390-4772, US, (606) 256-7288',
'237 Merry Campus, Twentysix, SC, 29330-4909, US, (864) 945-0157',
'446 Fallen Gate Rise, Petrolia, SC, 29959-9527, US, (864) 826-0553',
'2347 Indian Boulevard, Frisbee, VA, 23797-6458, US, (703) 656-8445',
'365 Emerald Grove Line, Level, NC, 28381-1514, US, (919) 976-7958',
'1207 Iron Extension, Klickitat, SC, 29197-8571, US, (803) 535-7888',
'6770 Cinder Glen, Caronport, OH, 45053-5002, US, (440) 369-4018',
'7619 Tawny Carrefour, Senlac, NV, 89529-9876, US, (775) 901-6433'];
'1197 Thunder Wagon Common, Cataract, RI, 02987-1016, US, (401) 747-0763',
'3685 Rocky Glade, Showtucket, NU, X1E-9I0, CA, (867) 371-4215',
'3235 High Forest, Glen Campbell, MS, 39035-6845, US, (601) 638-8186',
'2234 Sleepy Pony Mall , Drain, DC, 20078-4243, US, (202) 948-3634',
'2722 Hazy Turnabout, Burnt Cabins, NY, 14120-5642, US, (917) 604-6597',
'6686 Lazy Ledge, Two Rock, CA, 92639-3020, US, (619) 901-9911',
'2000 Dewy Limits, Wacahoota, NF, A4L-2V9, CA, (709) 065-3959',
'7710 Noble Pond Avenue, Bolivia, RI, 02931-1842, US, (401) 865-2160',
'3452 Sunny Vale, Pyro, ON, M8V-4Z0, CA, (519) 072-8609',
'4402 Dusty Cove, Many Farms, UT, 84853-8223, US, (435) 518-0673',
'5198 Silent Parade, Round Bottom, MD, 21542-9798, US, (301) 060-7245',
'8550 Shady Moor, Kitty Fork, CO, 80941-6207, US, (303) 502-3767',
'2131 Old Dell, Merry Midnight, AK, 99906-8842, US, (907) 369-2206',
'7390 Harvest Crest, Mosquito Crossing, RI, 02957-6116, US, (401) 463-6348',
'874 Little Point, Hot Coffee, BC, V3U-2P6, CA, (250) 706-9207',
'8834 Stony Pioneer Heights, Newlove, OR, 97419-8670, US, (541) 408-2213',
'9829 Grand Beach, Flint, UT, 84965-9900, US, (435) 700-5161',
'3799 Cozy Blossom Ramp, Ptarmigan, MS, 38715-0313, US, (769) 740-1526',
'3254 Silver Island Loop, Maunaloa, DE, 19869-3169, US, (302) 667-7671',
'1081 Middle Wood, Taylors Gut Landing, OR, 97266-2873, US, (541) 357-6310',
'1137 Umber Trail, Shacktown, NW, X3U-5Y8, CA, (867) 702-6883',
'9914 Hidden Bank, Wyoming, MO, 64635-9665, US, (636) 280-4192',
'7080 Misty Nectar Townline, Coward, AB, T9U-3N4, CA, (403) 623-2838',
'1184 Wishing Grounds, Vibank, NW, X7D-0V9, CA, (867) 531-2730',
'126 Easy Pointe, Grandview Beach, KY, 40928-9539, US, (502) 548-0956',
'6683 Colonial Street, Swan River, BC, V1A-9I8, CA, (778) 014-4257',
'960 Gentle Oak Lane, Shakopee, ND, 58618-6277, US, (701) 327-1219',
'6918 Cotton Pine Corner, Kenaston, IA, 52165-3975, US, (515) 906-7427',
'2368 Burning Woods, Ernfold, NY, 11879-9186, US, (646) 819-0355',
'5646 Quiet Shadow Chase, Tiger Tail, IA, 52283-5537, US, (712) 375-9225',
'5466 Foggy Mountain Dale, Sweet Home, MT, 59738-0251, US, (406) 881-1706',
'5313 Clear Willow Route, Amazon, BC, V0S-2S6, CA, (604) 340-7596',
'7000 Pleasant Autoroute, Spaceport City, UT, 84749-2448, US, (435) 154-3360',
'8359 Quaking Anchor Road, Gross, BC, V9O-0H5, CA, (250) 985-3859',
'5143 Amber Deer Hollow, New Deal, ND, 58446-0853, US, (701) 927-0322',
'6230 Jagged Bear Key, Young, AR, 72337-3811, US, (501) 805-7239',
'7207 Heather Vista, Devon, WY, 82520-1771, US, (307) 358-7092',
'9416 Red Rise Place, Spraytown, OK, 73809-4766, US, (580) 867-1973',
'3770 Golden Horse Diversion, Yelland, IL, 60471-1487, US, (224) 717-9349',
'4819 Honey Treasure Park, Alaska, NB, E1U-3I0, CA, (506) 656-9138',
'6187 Round Front, Land O Lakes, AK, 99873-6403, US, (907) 853-9063',
'9218 Crystal Highway, Pickelville, MT, 59847-9299, US, (406) 076-0024',
'6737 Bright Quay, Lazy Mountain, KY, 42390-4772, US, (606) 256-7288',
'237 Merry Campus, Twentysix, SC, 29330-4909, US, (864) 945-0157',
'446 Fallen Gate Rise, Petrolia, SC, 29959-9527, US, (864) 826-0553',
'2347 Indian Boulevard, Frisbee, VA, 23797-6458, US, (703) 656-8445',
'365 Emerald Grove Line, Level, NC, 28381-1514, US, (919) 976-7958',
'1207 Iron Extension, Klickitat, SC, 29197-8571, US, (803) 535-7888',
'6770 Cinder Glen, Caronport, OH, 45053-5002, US, (440) 369-4018',
'7619 Tawny Carrefour, Senlac, NV, 89529-9876, US, (775) 901-6433'];
RefData.IT_SKILLS = ['android', 'css', 'html5', 'mac', 'windows'];

View File

@@ -6,7 +6,6 @@ import DateComponent from "./DateComponent.jsx";
import SortableHeaderComponent from "./SortableHeaderComponent";
import "./RichGridExample.css";
// take this line out if you do not want to use ag-Grid-Enterprise
import "ag-grid-enterprise";
@@ -17,7 +16,6 @@ export default class RichGridExample extends Component {
this.state = {
quickFilterText: null,
showGrid: true,
showToolPanel: false,
columnDefs: new ColDefFactory().createColDefs(),
rowData: new RowDataFactory().createRowData(),
@@ -53,7 +51,8 @@ export default class RichGridExample extends Component {
}
},
// this is a simple property
rowBuffer: 10 // no need to set this, the default is fine for almost all scenarios
rowBuffer: 10, // no need to set this, the default is fine for almost all scenarios,
floatingFilter: true
};
this.onGridReady = this.onGridReady.bind(this);
@@ -61,12 +60,6 @@ export default class RichGridExample extends Component {
this.onCellClicked = this.onCellClicked.bind(this);
}
onShowGrid(show) {
this.setState({
showGrid: show
});
}
onToggleToolPanel(event) {
this.setState({showToolPanel: event.target.checked});
}
@@ -76,10 +69,6 @@ export default class RichGridExample extends Component {
this.columnApi = params.columnApi;
}
selectAll() {
this.api.selectAll();
}
deselectAll() {
this.api.deselectAll();
}
@@ -123,109 +112,219 @@ export default class RichGridExample extends Component {
// simply wait for the next tick
setTimeout(() => {
this.gridOptions.api.onFilterChanged();
},0)
}, 0)
}
render() {
let gridTemplate;
let bottomHeaderTemplate;
let topHeaderTemplate;
topHeaderTemplate = (
<div>
<div style={{float: 'right'}}>
<input type="text" onChange={this.onQuickFilterText.bind(this)}
placeholder="Type text to filter..."/>
<button id="btDestroyGrid" disabled={!this.state.showGrid}
onClick={this.onShowGrid.bind(this, false)}>Destroy Grid
</button>
<button id="btCreateGrid" disabled={this.state.showGrid} onClick={this.onShowGrid.bind(this, true)}>
Create Grid
</button>
return (
<div style={{width: '900px'}}>
<h1>Rich Grid Example</h1>
<div style={{display: "inline-block", width: "100%"}}>
<div style={{float: "left"}}>
<b>Employees Skills and Contact Details</b><span id="rowCount"/>
</div>
</div>
<div style={{padding: '4px'}}>
<b>Employees Skills and Contact Details</b> <span id="rowCount"/>
<div style={{marginTop: 10}}>
<div>
<span>
Grid API:
<button onClick={() => {
this.refs.myGrid.api.selectAll()
}} className="btn btn-primary">Select All</button>
<button onClick={this.deselectAll.bind(this)}
className="btn btn-primary">Clear Selection</button>
</span>
<span style={{float: "right"}}>
Column API:
<button onClick={this.setCountryVisible.bind(this, false)} className="btn btn-primary">Hide Country Column</button>
<button onClick={this.setCountryVisible.bind(this, true)} className="btn btn-primary">Show Country Column</button>
</span>
</div>
<div style={{display: "inline-block", width: "100%", marginTop: 10, marginBottom: 10}}>
<div style={{float: "left"}}>
<label>
<input type="checkbox" onChange={this.onToggleToolPanel.bind(this)}
style={{marginRight: 5}}/>
Show Tool Panel
</label>
</div>
<div style={{float: "left", marginLeft: 20}}>
<button onClick={this.onRefreshData.bind(this)} className="btn btn-primary">Refresh Data
</button>
</div>
<div style={{float: "left", marginLeft: 20}}>
<input type="text" onChange={this.onQuickFilterText.bind(this)}
placeholder="Type text to filter..."/>
</div>
<div style={{float: "right"}}>
Filter API:
<button onClick={this.invokeSkillsFilterMethod.bind(this, false)}
className="btn btn-primary">Invoke Skills Filter Method
</button>
<button onClick={this.dobFilter.bind(this)} className="btn btn-primary">DOB equals to
01/01/2000
</button>
</div>
</div>
<div style={{height: 400, width: 900}} className="ag-fresh">
<AgGridReact
ref="myGrid"
// gridOptions is optional - it's possible to provide
// all values as React props
gridOptions={this.gridOptions}
// listening for events
onGridReady={this.onGridReady}
onRowSelected={this.onRowSelected}
onCellClicked={this.onCellClicked}
// binding to simple properties
showToolPanel={this.state.showToolPanel}
quickFilterText={this.state.quickFilterText}
// binding to an object property
icons={this.state.icons}
// binding to array properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
// no binding, just providing hard coded strings for the properties
suppressRowClickSelection="true"
rowSelection="multiple"
enableColResize="true"
enableSorting="true"
enableFilter="true"
groupHeaders="true"
rowHeight="22"
/>
</div>
<div>
<div className="row">
<div className="col-sm-12"><h1>Rich Grid Example</h1></div>
</div>
<div className="row">
<div className="col-sm-12">
<h5>This example demonstrates many features of ag-Grid.</h5>
<p><span style={{fontWeight: 500}}>Select All/Clear Selection</span>: Select or Deselect
All
Rows</p>
<p><span style={{fontWeight: 500}}>Hide/Show Country Column</span>: Select or Deselect
All
Rows
(expand the Employee column to show the Country column first)</p>
<p><span style={{fontWeight: 500}}>Toggle The Tool Panel</span>: Let your users Pivot,
Group
and
Aggregate using the Tool Panel</p>
<p><span style={{fontWeight: 500}}>Refresh Data</span>: Dynamically Update Grid Data</p>
<p><span style={{fontWeight: 500}}>Quick Filter</span>: Perform Quick Grid Wide
Filtering
with
the Quick Filter</p>
<p><span style={{fontWeight: 500}}>DOB Filter</span>: Set the DOB filter to 01/01/2000
using
the
Filter API (expand the Employee column to show the DOB column)</p>
<p><span style={{fontWeight: 500}}>Custom Headers</span>: Sort, Filter and Render
Headers
using
Header Components</p>
</div>
</div>
<div className="row">
<div className="col-sm-4">
<div className="card">
<div className="card-body">
<h4 className="card-title">Grid & Column API</h4>
<p className="card-text">Utilise Grid Features Programmatically Using the APIs
Available</p>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-api/"
className="btn btn-primary">Grid API</a>
<a target="_blank" href="https://www.ag-grid.com//javascript-grid-column-api/"
className="btn btn-primary">Column API</a>
</div>
</div>
</div>
<div className="col-sm-4">
<div className="card">
<div className="card-body">
<h4 className="card-title">Header Components</h4>
<p className="card-text">Customer the Header with React Components</p>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-header-rendering/#headerComponent"
className="btn btn-primary">Header Component</a>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-header-rendering/#headerGroupComponent"
className="btn btn-primary">Header Group Component</a>
</div>
</div>
</div>
<div className="col-sm-4">
<div className="card">
<div className="card-body">
<h4 className="card-title">Filters</h4>
<p className="card-text">Filter with Quick Filters, Floating Filters, Built In
Filters
or Using the
Filter API</p>
<a target="_blank" href="https://www.ag-grid.com//javascript-grid-filter-quick/"
className="btn btn-primary">Quick
Filter</a>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-floating-filter-component/"
className="btn btn-primary">Floating Filters</a>
<a target="_blank" href="https://www.ag-grid.com//javascript-grid-filtering/"
className="btn btn-primary">Built in
Filters</a>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-filtering/#accessing-filter-component-instances"
className="btn btn-primary">Filter API</a>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-sm-4">
<div className="card">
<div className="card-body">
<h4 className="card-title">Tool Panel</h4>
<p className="card-text">Let your users Pivot, Group and Aggregate using the
Tool
Panel</p>
<a target="_blank" href="https://www.ag-grid.com//javascript-grid-tool-panel/"
className="btn btn-primary">Tool Panel</a>
</div>
</div>
</div>
<div className="col-sm-8">
<div className="card">
<div className="card-body">
<h4 className="card-title">The Rest</h4>
<p className="card-text">Pinned Columns, Checkbox Selection, Customer Renderers,
Data
Updates</p>
<a target="_blank"
href="https://www.ag-grid.com/best-react-data-grid/?framework=react"
className="btn btn-primary">React with ag-Grid</a>
<a target="_blank" href="https://www.ag-grid.com//javascript-grid-pinning/"
className="btn btn-primary">Pinned Column</a>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-selection/#checkboxSelection"
className="btn btn-primary">Checkbox Selection</a>
<a target="_blank"
href="https://www.ag-grid.com//javascript-grid-cell-rendering/"
className="btn btn-primary">Cell
Renderers</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-data-update/"
className="btn btn-primary">Updating Data</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
// showing the bottom header and grid is optional, so we put in a switch
if (this.state.showGrid) {
bottomHeaderTemplate = (
<div>
<div style={{padding: 4}} className={'toolbar'}>
<span>
Grid API:
<button onClick={this.selectAll.bind(this)}>Select All</button>
<button onClick={this.deselectAll.bind(this)}>Clear Selection</button>
</span>
<span style={{marginLeft: 20}}>
Column API:
<button onClick={this.setCountryVisible.bind(this, false)}>Hide Country Column</button>
<button onClick={this.setCountryVisible.bind(this, true)}>Show Country Column</button>
</span>
</div>
<div style={{clear: 'both'}}></div>
<div style={{padding: 4}} className={'toolbar'}>
<span>
<label>
<input type="checkbox" onChange={this.onToggleToolPanel.bind(this)}/>
Show Tool Panel
</label>
<button onClick={this.onRefreshData.bind(this)}>Refresh Data</button>
</span>
<span style={{marginLeft: 20}}>
Filter API:
<button onClick={this.invokeSkillsFilterMethod.bind(this, false)}>Invoke Skills Filter Method</button>
<button onClick={this.dobFilter.bind(this)}>DOB equals to 01/01/2000</button>
</span>
</div>
<div style={{clear: 'both'}}></div>
</div>
);
gridTemplate = (
<div style={{height: 400, width: 945}} className="ag-fresh">
<AgGridReact
// gridOptions is optional - it's possible to provide
// all values as React props
gridOptions={this.gridOptions}
// listening for events
onGridReady={this.onGridReady}
onRowSelected={this.onRowSelected}
onCellClicked={this.onCellClicked}
// binding to simple properties
showToolPanel={this.state.showToolPanel}
quickFilterText={this.state.quickFilterText}
// binding to an object property
icons={this.state.icons}
// binding to array properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
// no binding, just providing hard coded strings for the properties
suppressRowClickSelection="true"
rowSelection="multiple"
enableColResize="true"
enableSorting="true"
enableFilter="true"
groupHeaders="true"
rowHeight="22"
/>
</div>
);
}
return <div style={{width: '950px'}}>
<div style={{padding: '4px'}}>
{topHeaderTemplate}
{bottomHeaderTemplate}
{gridTemplate}
</div>
</div>;
}
}

View File

@@ -3,10 +3,10 @@ import RefData from './RefData';
export default class RowDataFactory {
createRowData() {
var rowData = [];
const rowData = [];
for (var i = 0; i < 200; i++) {
var countryData = RefData.COUNTRIES[i % RefData.COUNTRIES.length];
for (let i = 0; i < 200; i++) {
const countryData = RefData.COUNTRIES[i % RefData.COUNTRIES.length];
rowData.push({
name: RefData.FIRST_NAMES[i % RefData.FIRST_NAMES.length] + ' ' + RefData.LAST_NAMES[i % RefData.LAST_NAMES.length],
skills: {
@@ -32,8 +32,8 @@ export default class RowDataFactory {
}
createRandomPhoneNumber() {
var result = '+';
for (var i = 0; i < 12; i++) {
let result = '+';
for (let i = 0; i < 12; i++) {
result += Math.round(Math.random() * 10);
if (i === 2 || i === 5 || i === 8) {
result += ' ';

View File

@@ -5,11 +5,11 @@ import RefData from './RefData';
export default class SkillsCellRenderer extends React.Component {
render() {
var skills = [];
var rowData = this.props.data;
RefData.IT_SKILLS.forEach( (skill) => {
const skills = [];
const rowData = this.props.data;
RefData.IT_SKILLS.forEach((skill) => {
if (rowData && rowData.skills && rowData.skills[skill]) {
skills.push(<img key={skill} src={'images/skills/' + skill + '.png'} width={16} title={skill} />);
skills.push(<img key={skill} src={'images/skills/' + skill + '.png'} width={16} title={skill}/>);
}
});

View File

@@ -42,10 +42,10 @@ export default class SkillsFilter extends React.Component {
// called by agGrid
doesFilterPass(params) {
var rowSkills = params.data.skills;
var passed = true;
const rowSkills = params.data.skills;
let passed = true;
RefData.IT_SKILLS.forEach( (skill) => {
RefData.IT_SKILLS.forEach((skill) => {
if (this.state[skill]) {
if (!rowSkills[skill]) {
passed = false;
@@ -56,19 +56,23 @@ export default class SkillsFilter extends React.Component {
return passed;
};
getModel() {
return ''
}
// called by agGrid
isFilterActive() {
var somethingSelected = this.state.android || this.state.css ||
const somethingSelected = this.state.android || this.state.css ||
this.state.html5 || this.state.mac || this.state.windows;
return somethingSelected;
};
onSkillChanged(skill, event) {
var newValue = event.target.checked;
var newModel = {};
const newValue = event.target.checked;
const newModel = {};
newModel[skill] = newValue;
// set the state, and once it is done, then call filterChangedCallback
this.setState(newModel, this.props.filterChangedCallback );
this.setState(newModel, this.props.filterChangedCallback);
}
helloFromSkillsFilter() {
@@ -77,17 +81,18 @@ export default class SkillsFilter extends React.Component {
render() {
var skillsTemplates = [];
RefData.IT_SKILLS.forEach( (skill, index) => {
const skillsTemplates = [];
RefData.IT_SKILLS.forEach((skill, index) => {
var skillName = RefData.IT_SKILLS_NAMES[index];
var template = (
<label key={skill} style={{border: '1px solid lightgrey', margin: 4, padding: 4, display: 'inline-block'}}>
const skillName = RefData.IT_SKILLS_NAMES[index];
const template = (
<label key={skill}
style={{border: '1px solid lightgrey', margin: 4, padding: 4, display: 'inline-block'}}>
<span>
<div style={{textAlign: 'center'}}>{skillName}</div>
<div>
<input type="checkbox" onClick={this.onSkillChanged.bind(this, skill)}/>
<img src={'images/skills/'+skill+'.png'} width={30}/>
<img src={'images/skills/' + skill + '.png'} width={30}/>
</div>
</span>
</label>
@@ -98,7 +103,13 @@ export default class SkillsFilter extends React.Component {
return (
<div style={{width: 380}}>
<div style={{textAlign: 'center', background: 'lightgray', width: '100%', display: 'block', borderBottom: '1px solid grey'}}>
<div style={{
textAlign: 'center',
background: 'lightgray',
width: '100%',
display: 'block',
borderBottom: '1px solid grey'
}}>
<b>Custom Skills Filter</b>
</div>
{skillsTemplates}

View File

@@ -7,7 +7,8 @@ export default class SortableHeaderComponent extends React.Component {
constructor(props) {
super(props);
this.props.column.addEventListener('sortChanged', this.onSortChanged.bind(this));
// this.sortChanged = this.onSortChanged.bind(this);
this.props.column.addEventListener('sortChanged', this.onSortChanged);
//The state of this component contains the current sort state of this column
//The possible values are: 'asc', 'desc' and ''
@@ -16,6 +17,9 @@ export default class SortableHeaderComponent extends React.Component {
}
}
componentWillUnmount() {
this.props.column.removeEventListener('sortChanged', this.onSortChanged);
}
render() {
let sortElements = [];
@@ -24,11 +28,14 @@ export default class SortableHeaderComponent extends React.Component {
let upArrowClass = "customSortUpLabel " + (this.state.sorted === 'asc' ? " active" : "");
let removeArrowClass = "customSortRemoveLabel " + (this.state.sorted === '' ? " active" : "");
sortElements.push(<div key={`up${this.props.displayName}`} className={downArrowClass} onClick={this.onSortRequested.bind(this, 'desc')}><i
className="fa fa-long-arrow-down"/></div>)
sortElements.push(<div key={`down${this.props.displayName}`} className={upArrowClass} onClick={this.onSortRequested.bind(this, 'asc')}><i
className="fa fa-long-arrow-up"/></div>)
sortElements.push(<div key={`minus${this.props.displayName}`} className={removeArrowClass} onClick={this.onSortRequested.bind(this, '')}><i
sortElements.push(<div key={`up${this.props.displayName}`} className={downArrowClass}
onClick={this.onSortRequested.bind(this, 'desc')}><i
className="fa fa-long-arrow-down"/></div>);
sortElements.push(<div key={`down${this.props.displayName}`} className={upArrowClass}
onClick={this.onSortRequested.bind(this, 'asc')}><i
className="fa fa-long-arrow-up"/></div>);
sortElements.push(<div key={`minus${this.props.displayName}`} className={removeArrowClass}
onClick={this.onSortRequested.bind(this, '')}><i
className="fa fa-times"/></div>)
}
@@ -51,7 +58,7 @@ export default class SortableHeaderComponent extends React.Component {
this.props.setSort(order, event.shiftKey);
};
onSortChanged() {
onSortChanged = () => {
if (this.props.column.isSortAscending()) {
this.setState({
sorted: 'asc'

View File

@@ -0,0 +1,57 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import {connect} from "react-redux";
import PriceRenderer from "./PriceRenderer";
/*
* 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', cellClass: 'align-right', cellRendererFramework: PriceRenderer}
]
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
// row data will be provided via redux on this.props.rowData
render() {
return (
<div style={{height: 400, width: 900, marginTop: 15}}
className="ag-fresh">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.props.rowData}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
)
}
}
// pull off row data changes
export default connect(
(state) => {
return {
rowData: state.rowData
}
}
)(GridComponent);

View File

@@ -0,0 +1,85 @@
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 {setCurrency, 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);
}
componentDidMount() {
// provide the initial data to the store (which in turn will populate the grid)
this.props.dispatch(updateRowData(this.createRowData()));
}
setCurrency(currencySymbol, exchangeRate) {
this.props.dispatch(setCurrency(currencySymbol, exchangeRate));
}
render() {
return (
<div style={{marginTop: 15}}>
<button onClick={this.setCurrency.bind(this, '£', 1)}>Set Currency to GBP</button>
<button onClick={this.setCurrency.bind(this, '$', 1.29)}>Set Currency to USD</button>
</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 {
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
export default connect(
(state) => {
return {
rowData: state.rowData
}
}
)(HeaderComponent);

View File

@@ -0,0 +1,37 @@
import React, {Component} from "react";
import {connect} from "react-redux";
class PriceRenderer extends Component {
constructor(props) {
super(props);
this.state = {
convertedValue: this.applyExchangeRate(props.exchangeRate, props.value)
};
}
componentWillReceiveProps(nextProps) {
this.setState({
convertedValue: this.applyExchangeRate(nextProps.exchangeRate, nextProps.value)
})
}
render() {
return (
<span>{this.props.currencySymbol}{this.state.convertedValue}</span>
);
}
applyExchangeRate = (exchangeRate, value) => {
return parseFloat(value * exchangeRate).toFixed(2); // simplified/naive exchange rate implementation!
}
}
export default connect(
(state) => {
return {
currencySymbol: state.currencySymbol,
exchangeRate: state.exchangeRate
}
}
)(PriceRenderer);

View File

@@ -0,0 +1,34 @@
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);
}
render() {
return (
<Provider store={store}>
<div>
<h1>Simple Redux Example using Connected React Components</h1>
<HeaderComponent />
<GridComponent />
</div>
</Provider>
)
}
};

View File

@@ -0,0 +1,13 @@
export function updateRowData(rowData) {
return {
type: 'ROW_DATA_CHANGED',
rowData
}
}
export function setCurrency(currencySymbol, exchangeRate) {
return {
type: 'CURRENCY_CHANGED',
currencySymbol,
exchangeRate
}
}

View File

@@ -0,0 +1,17 @@
export default (state = {rowData: [], currencySymbol: '£', exchangeRate: 1}, action) => {
switch (action.type) {
case 'ROW_DATA_CHANGED':
return {
...state,
rowData: action.rowData,
};
case 'CURRENCY_CHANGED':
return {
...state,
currencySymbol: action.currencySymbol,
exchangeRate: action.exchangeRate
};
default:
return state;
}
};

View File

@@ -62,7 +62,7 @@ class GridComponent extends Component {
// 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}}
<div style={{height: 400, width: 900, marginTop: 15}}
className="ag-fresh">
<AgGridReact
// properties