Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fdb563a0e | ||
|
|
7a5e15c8cd | ||
|
|
bf18305c9a | ||
|
|
aef9c596b6 | ||
|
|
2d5fea4790 | ||
|
|
c680bffd5a | ||
|
|
917277bfe1 | ||
|
|
d2cb2149cc | ||
|
|
0954bec3ee | ||
|
|
89d76cd1ac | ||
|
|
52cf4512a9 | ||
|
|
611d668981 | ||
|
|
5ad3592fed | ||
|
|
ff7c46e553 | ||
|
|
1c1e1bf555 | ||
|
|
6ad4493357 | ||
|
|
1cf70a551e | ||
|
|
fcc2bfffcd | ||
|
|
3e8b1b7979 | ||
|
|
61420e0d67 | ||
|
|
bd63d49c52 | ||
|
|
36eb9c8a18 | ||
|
|
b4c3ebc248 | ||
|
|
51621200da | ||
|
|
46c26f074e | ||
|
|
894d971f0e | ||
|
|
0584234be7 | ||
|
|
b9b2b03a6b | ||
|
|
5a26863aff | ||
|
|
3223b82616 | ||
|
|
70f747e9f3 | ||
|
|
29152268bc | ||
|
|
cda61736cf | ||
|
|
e55950227f | ||
|
|
940cc314aa | ||
|
|
5e4a94d865 | ||
|
|
efa5167c54 | ||
|
|
6b06b9fa01 | ||
|
|
eecd2a6bb2 | ||
|
|
ec4f7dea27 | ||
|
|
3d7774e7c7 | ||
|
|
92ad56ed49 | ||
|
|
7ff41a6966 | ||
|
|
74ccfa6b26 | ||
|
|
e07c66c95d | ||
|
|
cb438ce67b | ||
|
|
3f0fe9f899 | ||
|
|
a3a1d74b88 | ||
|
|
2b49fb1b01 | ||
|
|
c338f851e0 | ||
|
|
58df719d45 | ||
|
|
2b6e3e8f41 | ||
|
|
f470a4c33d | ||
|
|
b51caf4746 | ||
|
|
30746397ef | ||
|
|
4998a51817 | ||
|
|
518a95ee89 | ||
|
|
3debbabe28 | ||
|
|
550f6c4077 | ||
|
|
99bc479b60 | ||
|
|
f5c1a4ba17 | ||
|
|
168a127e51 | ||
|
|
f9b1f8527a | ||
|
|
eee938e0e7 | ||
|
|
449a88e832 | ||
|
|
60181add9a | ||
|
|
847005c758 | ||
|
|
ca64dae64c | ||
|
|
3591b78e4b | ||
|
|
2fedd32efd | ||
|
|
849472a031 | ||
|
|
a2743f9076 | ||
|
|
d9724f7ab5 | ||
|
|
c0443ba6ef | ||
|
|
88752be90b | ||
|
|
2080ebb054 | ||
|
|
172c2a05b0 | ||
|
|
badb5ea485 | ||
|
|
c3af000642 | ||
|
|
7b6b609cdf | ||
|
|
5ffb682014 | ||
|
|
de18262157 | ||
|
|
1f6c1e41a1 | ||
|
|
ba3762bbd3 | ||
|
|
455f982d6c | ||
|
|
0c927ae3c5 | ||
|
|
2bd8d4c987 | ||
|
|
318f78de84 | ||
|
|
9ca52a727d | ||
|
|
56ccdd028c | ||
|
|
a5ccb6d622 | ||
|
|
25e1f1c184 | ||
|
|
8dd0f96b32 | ||
|
|
cf0796eb84 | ||
|
|
a64626e67e | ||
|
|
95445e558c | ||
|
|
79a6206026 | ||
|
|
f8ac0e5c98 | ||
|
|
06d9e88e88 | ||
|
|
f860a740f3 | ||
|
|
90ec337474 | ||
|
|
05d4341dfc | ||
|
|
df77361fd4 | ||
|
|
983b5974cf | ||
|
|
b030235bbc | ||
|
|
351d93b8fb | ||
|
|
43af1237bd | ||
|
|
fc76e85d77 | ||
|
|
6979c51eaf | ||
|
|
f035ee7a9d | ||
|
|
a982e0f2a7 | ||
|
|
cbb4a31be6 | ||
|
|
d2b92b4c9a | ||
|
|
c8267730bf | ||
|
|
3992e3e928 | ||
|
|
8409183d6b | ||
|
|
7075f57d88 | ||
|
|
ad6bc068b2 | ||
|
|
c4310c2768 | ||
|
|
2228a8d0c9 | ||
|
|
966fa0fe69 | ||
|
|
9528d5a5bc | ||
|
|
3b5eaac21a | ||
|
|
73cc989512 | ||
|
|
5a45846cb7 | ||
|
|
2d8d5b125e | ||
|
|
818b7798ee | ||
|
|
15ba8d7e60 | ||
|
|
eab958c3e9 | ||
|
|
3a17b7f638 | ||
|
|
734d39e2d7 | ||
|
|
0d7cace354 | ||
|
|
fa0881bfcf | ||
|
|
62b9e3582a | ||
|
|
949797d4be | ||
|
|
a869fe3819 | ||
|
|
c611af4f39 | ||
|
|
7cab3190ae | ||
|
|
71fe653fcb | ||
|
|
ba1c213ce0 | ||
|
|
46217c9ad7 | ||
|
|
017642e4d7 | ||
|
|
79b0eda61b | ||
|
|
a70f248af5 |
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
/node_modules
|
||||
/dist
|
||||
package-lock.json
|
||||
*.nosync
|
||||
|
||||
19
README.md
@@ -1,29 +1,18 @@
|
||||
|
||||
ag-Grid React Example
|
||||
==============
|
||||
|
||||
Examples of running ag-Grid inside React application.
|
||||
|
||||
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:
|
||||
## Examples
|
||||
|
||||
1. standard - shows a typical grid demonstrating many ag-Grid features
|
||||
|
||||
2. large - shows a very large grid (767 columns and 1,000 rows) using React cell renderers
|
||||
|
||||
See [www.ag-grid.com](http://www.ag-grid.com) for full documentation and examples.
|
||||
|
||||
Building
|
||||
==============
|
||||
|
||||
To build:
|
||||
- `npm install`
|
||||
- `npm install webpack -g`
|
||||
- `npm run example`, `npm run large` or `npm run trader`
|
||||
- `npm run examples`, `npm run large` or `npm run trader`
|
||||
- navigate to localhost:8080
|
||||
52
config/webpack.config.examples.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const path = require('path');
|
||||
|
||||
const SRC_DIR = path.resolve(__dirname, '../src-examples');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: SRC_DIR + "/index.js",
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../'),
|
||||
filename: "dist/react-examples.js"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: "style-loader!css-loader"
|
||||
},
|
||||
{
|
||||
test: /\.js$|\.jsx$/,
|
||||
include: SRC_DIR,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
presets: ['@babel/preset-react', '@babel/preset-env'],
|
||||
plugins: [
|
||||
require('@babel/plugin-proposal-function-bind'),
|
||||
require('@babel/plugin-proposal-class-properties')
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
|
||||
loader: 'file-loader?name=[path]/[name].[ext]'
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
// "@ag-grid-community/core/modules": path.resolve('./node_modules/@ag-grid-community/core/dist/es2015/modules'),
|
||||
"@ag-grid-community/core": path.resolve('./node_modules/@ag-grid-community/core'),
|
||||
// "ag-grid-enterprise": path.resolve('./node_modules/ag-grid-enterprise'),
|
||||
react: path.resolve('./node_modules/react')
|
||||
},
|
||||
extensions: ['.js', '.jsx']
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
devServer: {
|
||||
port: 8080,
|
||||
historyApiFallback: true
|
||||
}
|
||||
};
|
||||
46
config/webpack.config.large.js
Normal file
@@ -0,0 +1,46 @@
|
||||
const path = require('path');
|
||||
|
||||
const SRC_DIR = path.resolve(__dirname, '../src-large-data');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: SRC_DIR + "/index.js",
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../'),
|
||||
filename: "dist/react-large.js"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: "style-loader!css-loader"
|
||||
},
|
||||
{
|
||||
test: /\.js$|\.jsx$/,
|
||||
include: SRC_DIR,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
presets: ['@babel/preset-react', '@babel/preset-env'],
|
||||
plugins: [
|
||||
require('@babel/plugin-proposal-function-bind'),
|
||||
require('@babel/plugin-proposal-class-properties')
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@ag-grid-community/core": path.resolve('./node_modules/@ag-grid-community/core'),
|
||||
"ag-grid-enterprise": path.resolve('./node_modules/ag-grid-enterprise'),
|
||||
react: path.resolve('./node_modules/react')
|
||||
},
|
||||
extensions: ['.js', '.jsx']
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
devServer: {
|
||||
port: 8080,
|
||||
}
|
||||
};
|
||||
46
config/webpack.config.trader.js
Normal file
@@ -0,0 +1,46 @@
|
||||
const path = require('path');
|
||||
|
||||
const SRC_DIR = path.resolve(__dirname, '../src-trader-dashboard');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: SRC_DIR + "/index.js",
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../'),
|
||||
filename: "dist/react-trader.js"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: "style-loader!css-loader"
|
||||
},
|
||||
{
|
||||
test: /\.js$|\.jsx$/,
|
||||
include: SRC_DIR,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
presets: ['@babel/preset-react', '@babel/preset-env'],
|
||||
plugins: [
|
||||
require('@babel/plugin-proposal-function-bind'),
|
||||
require('@babel/plugin-proposal-class-properties')
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@ag-grid-community/core": path.resolve('./node_modules/@ag-grid-community/core'),
|
||||
"ag-grid-enterprise": path.resolve('./node_modules/ag-grid-enterprise'),
|
||||
react: path.resolve('./node_modules/react')
|
||||
},
|
||||
extensions: ['.js', '.jsx']
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
devServer: {
|
||||
port: 8080,
|
||||
}
|
||||
};
|
||||
26
gulpfile.js
Normal 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);
|
||||
}
|
||||
8618
olympicWinners.json
79
package.json
@@ -1,29 +1,30 @@
|
||||
{
|
||||
"name": "ag-grid-react-example",
|
||||
"version": "12.0.0",
|
||||
"version": "23.0.2",
|
||||
"description": "Example Reach applicaiton using ag-Grid.",
|
||||
"main": "dist/ag-grid-react-example.js",
|
||||
"scripts": {
|
||||
"trader": "webpack-dev-server --content-base src-trader-dashboard/ --config webpack.config.trader.js --progress --colors --hot --inline",
|
||||
"examples": "webpack-dev-server --content-base src/ --config webpack.config.examples.js --progress --colors --hot --inline",
|
||||
"large": "webpack-dev-server --config webpack.config.large.js --progress --colors --hot --inline",
|
||||
"trader": "webpack-dev-server --content-base src-trader-dashboard/ --config config/webpack.config.trader.js --mode development --open",
|
||||
"examples": "webpack-dev-server --content-base src-examples/ --config config/webpack.config.examples.js --mode development --open",
|
||||
"large": "webpack-dev-server --content-base src-large-data/ --config config/webpack.config.large.js --mode development --open",
|
||||
"clean": "rimraf dist",
|
||||
"mkdirs": "mkdirp dist/trader/dist dist/examples/dist",
|
||||
"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-examples": "ncp src-examples/images dist/examples/images && ncp src-examples/index.html dist/examples/index.html && ncp dist/react-examples.js dist/examples/dist/react-examples.js && ncp src-examples/ 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-examples": "webpack --config webpack.config.examples.js --progress --profile --bail",
|
||||
"build-dashboard": "webpack --config webpack.config.trader.js --progress --profile --bail",
|
||||
"build-large": "webpack --config config/webpack.config.large.js --progress --profile --bail",
|
||||
"build-examples": "webpack --config config/webpack.config.examples.js --progress --profile --bail",
|
||||
"build-dashboard": "webpack --config 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",
|
||||
"build-to-docs": "npm run build && npm run copy-to-docs",
|
||||
"start": "npm run examples"
|
||||
"start": "npm run examples",
|
||||
"test": "./ts-tests/runTsTests.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ceolter/ag-grid-react-example.git"
|
||||
"url": "https://github.com/ag-grid/ag-grid-react-example.git"
|
||||
},
|
||||
"private": true,
|
||||
"keywords": [
|
||||
"react",
|
||||
"grid",
|
||||
@@ -33,39 +34,43 @@
|
||||
"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": {
|
||||
"babel-core": "6.24.x",
|
||||
"babel-loader": "6.4.x",
|
||||
"babel-preset-es2015": "6.24.x",
|
||||
"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",
|
||||
"@ag-grid-community/core": "~23.0.0",
|
||||
"@babel/core": "7.4.4",
|
||||
"@babel/plugin-proposal-class-properties": "7.4.4",
|
||||
"@babel/plugin-proposal-function-bind": "7.2.0",
|
||||
"@babel/preset-env": "7.4.4",
|
||||
"@babel/preset-react": "7.0.0",
|
||||
"@types/react": "16.9.2",
|
||||
"@types/react-dom": "16.9.0",
|
||||
"babel-loader": "8.0.6",
|
||||
"css-loader": "2.1.1",
|
||||
"file-loader": "3.0.1",
|
||||
"gulp": "3.9.1",
|
||||
"merge2": "1.2.3",
|
||||
"mkdirp": "0.5.1",
|
||||
"ncp": "2.0.0",
|
||||
"rimraf": "2.5.x",
|
||||
"style-loader": "0.13.x",
|
||||
"webpack": "1.12.x",
|
||||
"webpack-dev-server": "1.14.x"
|
||||
"prop-types": "15.7.2",
|
||||
"rimraf": "2.6.3",
|
||||
"style-loader": "0.23.1",
|
||||
"typescript": "3.4.5",
|
||||
"webpack": "4.31.0",
|
||||
"webpack-cli": "3.3.2",
|
||||
"webpack-dev-server": "3.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "3.3.7",
|
||||
"@ag-grid-enterprise/all-modules": "~23.0.0",
|
||||
"@ag-grid-community/react": "~23.0.0",
|
||||
"bootstrap": "4.4.1",
|
||||
"d3": "4.9.1",
|
||||
"file-loader": "0.11.1",
|
||||
"lodash": "4.17.4",
|
||||
"react": "15.5.x",
|
||||
"react-dom": "15.5.x",
|
||||
"react-redux": "5.0.x",
|
||||
"redux": "3.6.x",
|
||||
"url-search-params-polyfill": "1.2.0",
|
||||
"ag-grid": "12.0.x",
|
||||
"ag-grid-enterprise": "12.0.x",
|
||||
"ag-grid-react": "12.0.x"
|
||||
"lodash": "4.17.11",
|
||||
"react": "16.8.6",
|
||||
"react-dom": "16.8.6",
|
||||
"react-redux": "7.0.3",
|
||||
"react-router-dom": "5.0.0",
|
||||
"redux": "4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
src-examples/App.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, {Component} from "react";
|
||||
import {Redirect, Route, Switch} from "react-router-dom";
|
||||
|
||||
import NavItem from "./NavItem";
|
||||
import RichGridDeclarativeExample from "./richGridDeclarativeExample/RichGridDeclarativeExample";
|
||||
import SimpleReduxDynamicExample from "./simpleReduxDynamicComponentExample/SimpleReduxExample";
|
||||
import SimpleReduxHookExample from "./simpleReduxHooksExample/SimpleReduxHookExample";
|
||||
|
||||
const SideBar = () => (
|
||||
<div style={{float: "left", width: 335, marginRight: 25}}>
|
||||
<ul className="nav nav-pills">
|
||||
<NavItem to='/rich-grid-declarative'>Rich Grid with Declarative Markup</NavItem>
|
||||
<NavItem to='/simple-redux-dynamic'>Simple Redux Dynamic Component Example</NavItem>
|
||||
<NavItem to='/simple-redux-hook'>Simple React Hook 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-declarative"/>
|
||||
<Route exact path='/rich-grid-declarative' component={RichGridDeclarativeExample}/>
|
||||
<Route exact path='/simple-redux-dynamic' component={SimpleReduxDynamicExample}/>
|
||||
<Route exact path='/simple-redux-hook' component={SimpleReduxHookExample}/>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
20
src-examples/NavItem.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react'
|
||||
import * as PropTypes from 'prop-types';
|
||||
import {Link, Route} 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="nav-item">
|
||||
<Link className={match ? 'nav-link active' : 'nav-link'} to={to}>{children}</Link>
|
||||
</li>
|
||||
)}/>
|
||||
)
|
||||
}
|
||||
|
||||
NavItem.propTypes = {
|
||||
to: PropTypes.string.isRequired,
|
||||
exact: PropTypes.bool,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 606 B |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 256 B After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B |
|
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
|
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 89 B After Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 227 B After Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 97 B After Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 222 B |
|
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 739 B After Width: | Height: | Size: 739 B |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 902 B After Width: | Height: | Size: 902 B |
|
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 394 B |
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 893 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 570 B After Width: | Height: | Size: 570 B |
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="dist/react-examples.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../dist/react-examples.js" charset="utf-8"></script>
|
||||
<!-- Example uses font awesome icons -->
|
||||
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
|
||||
@@ -12,40 +12,55 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
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,13 +73,11 @@
|
||||
|
||||
.customHeaderLabel {
|
||||
margin-left: 5px;
|
||||
margin-top: 3px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.customExpandButton {
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
25
src-examples/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
import React from "react";
|
||||
import {render} from "react-dom";
|
||||
import {BrowserRouter} from "react-router-dom";
|
||||
|
||||
import "@ag-grid-enterprise/all-modules/dist/styles/ag-grid.css";
|
||||
import "@ag-grid-enterprise/all-modules/dist/styles/ag-theme-balham.css";
|
||||
import "../node_modules/bootstrap/dist/css/bootstrap.css";
|
||||
|
||||
import App from "./App";
|
||||
|
||||
// only required when using enterprise features
|
||||
// import {LicenseManager} from "@ag-grid-enterprise/all-modules";
|
||||
// LicenseManager.setLicenseKey("<your license key>");
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
render(
|
||||
<BrowserRouter>
|
||||
<App/>
|
||||
</BrowserRouter>,
|
||||
document.querySelector('#app')
|
||||
);
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ export default class DateComponent extends React.Component {
|
||||
width: '30px'
|
||||
};
|
||||
let yyyyStyle = {
|
||||
width: '60px'
|
||||
width: '40px'
|
||||
};
|
||||
let resetStyle = {
|
||||
padding: '2px',
|
||||
@@ -51,11 +51,11 @@ export default class DateComponent extends React.Component {
|
||||
return (
|
||||
<div style={filterStyle}>
|
||||
<span style={resetStyle} onClick={this.resetDate.bind(this)}>x</span>
|
||||
<input onInput={this.onDateChanged.bind(this)} ref="dd" placeholder="dd" style={ddStyle}
|
||||
<input onChange={this.onDateChanged.bind(this)} ref="dd" placeholder="dd" style={ddStyle}
|
||||
value={this.state.textBoxes.dd} maxLength="2"/>/
|
||||
<input onInput={this.onDateChanged.bind(this)} ref="mm" placeholder="mm" style={mmStyle}
|
||||
<input onChange={this.onDateChanged.bind(this)} ref="mm" placeholder="mm" style={mmStyle}
|
||||
value={this.state.textBoxes.mm} maxLength="2"/>/
|
||||
<input onInput={this.onDateChanged.bind(this)} ref="yyyy" placeholder="yyyy" style={yyyyStyle}
|
||||
<input onChange={this.onDateChanged.bind(this)} ref="yyyy" placeholder="yyyy" style={yyyyStyle}
|
||||
value={this.state.textBoxes.yyyy} maxLength="4"/>
|
||||
</div>
|
||||
);
|
||||
@@ -21,7 +21,8 @@ export default class HeaderGroupComponent extends React.Component {
|
||||
|
||||
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>
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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,28 @@ 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 ''
|
||||
}
|
||||
|
||||
setModel(model) {
|
||||
}
|
||||
|
||||
render() {
|
||||
var rows = [];
|
||||
const rows = [];
|
||||
PROFICIENCY_NAMES.forEach((name) => {
|
||||
var selected = this.state.selected === name;
|
||||
const selected = this.state.selected === name;
|
||||
rows.push(
|
||||
<div key={name}>
|
||||
<div key={name} style={{marginTop: 3}}>
|
||||
<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 +66,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}
|
||||
129
src-examples/richGridDeclarativeExample/RefData.js
Normal file
@@ -0,0 +1,129 @@
|
||||
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"
|
||||
];
|
||||
|
||||
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"
|
||||
];
|
||||
|
||||
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"
|
||||
};
|
||||
|
||||
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"}
|
||||
];
|
||||
|
||||
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)
|
||||
];
|
||||
|
||||
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'];
|
||||
|
||||
RefData.IT_SKILLS = ['android', 'css', 'html5', 'mac', 'windows'];
|
||||
|
||||
RefData.IT_SKILLS_NAMES = ['Android', 'CSS', 'HTML 5', 'Mac', 'Windows'];
|
||||
@@ -0,0 +1,261 @@
|
||||
import React, { Component } from "react";
|
||||
import { AgGridColumn, AgGridReact } from "@ag-grid-community/react";
|
||||
import RowDataFactory from "./RowDataFactory";
|
||||
import DateComponent from "./DateComponent.jsx";
|
||||
import SkillsCellRenderer from './SkillsCellRenderer.jsx';
|
||||
import NameCellEditor from './NameCellEditor.jsx';
|
||||
import ProficiencyCellRenderer from './ProficiencyCellRenderer.jsx';
|
||||
import RefData from './RefData';
|
||||
import SkillsFilter from './SkillsFilter.jsx';
|
||||
import ProficiencyFilter from './ProficiencyFilter.jsx';
|
||||
import HeaderGroupComponent from './HeaderGroupComponent.jsx';
|
||||
import SortableHeaderComponent from './SortableHeaderComponent.jsx';
|
||||
|
||||
import "./RichGridDeclarativeExample.css";
|
||||
|
||||
// for community features
|
||||
// import {AllCommunityModules} from "@ag-grid-community/all-modules";
|
||||
|
||||
// for enterprise features
|
||||
import { AllModules } from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
export default class RichGridDeclarativeExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
quickFilterText: null,
|
||||
sideBar: false,
|
||||
rowData: new RowDataFactory().createRowData(),
|
||||
rowCount: null,
|
||||
icons: {
|
||||
columnRemoveFromGroup: '<i class="fa fa-times"/>',
|
||||
filter: '<i class="fa fa-filter"/>',
|
||||
sortAscending: '<i class="fa fa-long-arrow-down"/>',
|
||||
sortDescending: '<i class="fa fa-long-arrow-up"/>',
|
||||
groupExpanded: '<i class="fa fa-minus-square-o"/>',
|
||||
groupContracted: '<i class="fa fa-plus-square-o"/>'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* Grid Events we're listening to */
|
||||
onGridReady = (params) => {
|
||||
this.api = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.calculateRowCount();
|
||||
};
|
||||
|
||||
onCellClicked = (event) => {
|
||||
console.log('onCellClicked: ' + event.data.name + ', col ' + event.colIndex);
|
||||
};
|
||||
|
||||
onRowSelected = (event) => {
|
||||
console.log('onRowSelected: ' + event.node.data.name);
|
||||
};
|
||||
|
||||
/* Demo related methods */
|
||||
onToggleSidebar = (event) => {
|
||||
this.setState({ sideBar: event.target.checked });
|
||||
};
|
||||
|
||||
deselectAll() {
|
||||
this.api.deselectAll();
|
||||
}
|
||||
|
||||
onQuickFilterText = (event) => {
|
||||
this.setState({ quickFilterText: event.target.value });
|
||||
};
|
||||
|
||||
onRefreshData = () => {
|
||||
this.setState({
|
||||
rowData: new RowDataFactory().createRowData()
|
||||
});
|
||||
};
|
||||
|
||||
invokeSkillsFilterMethod = () => {
|
||||
this.api.getFilterInstance('skills', (instance) => {
|
||||
let componentInstance = instance.getFrameworkComponentInstance();
|
||||
componentInstance.helloFromSkillsFilter();
|
||||
});
|
||||
};
|
||||
|
||||
dobFilter = () => {
|
||||
this.api.getFilterInstance('dob', (dateFilterComponent) => {
|
||||
dateFilterComponent.setModel({
|
||||
type: 'equals',
|
||||
dateFrom: '2000-01-01'
|
||||
});
|
||||
|
||||
// as the date filter is a React component, and its using setState internally, we need
|
||||
// to allow time for the state to be set (as setState is an async operation)
|
||||
// simply wait for the next tick
|
||||
setTimeout(() => {
|
||||
this.api.onFilterChanged();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
calculateRowCount = () => {
|
||||
if (this.api && this.state.rowData) {
|
||||
const model = this.api.getModel();
|
||||
const totalRows = this.state.rowData.length;
|
||||
const processedRows = model.getRowCount();
|
||||
this.setState({
|
||||
rowCount: processedRows.toLocaleString() + ' / ' + totalRows.toLocaleString()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static countryCellRenderer(params) {
|
||||
if (params.value) {
|
||||
return `<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'> ${params.value}`;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static dateCellRenderer(params) {
|
||||
return RichGridDeclarativeExample.pad(params.value.getDate(), 2) + '/' +
|
||||
RichGridDeclarativeExample.pad(params.value.getMonth() + 1, 2) + '/' +
|
||||
params.value.getFullYear();
|
||||
}
|
||||
|
||||
static pad(num, totalStringSize) {
|
||||
let asString = num + "";
|
||||
while (asString.length < totalStringSize) asString = "0" + asString;
|
||||
return asString;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ width: '900px' }}>
|
||||
<h1>Rich Grid with Declarative Markup Example</h1>
|
||||
<div style={{ display: "inline-block", width: "100%" }}>
|
||||
<div style={{ float: "left" }}>
|
||||
<b>Employees Skills and Contact Details: </b>{this.state.rowCount}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<div>
|
||||
<span>
|
||||
Grid API:
|
||||
<button onClick={() => {
|
||||
this.api.selectAll();
|
||||
}} className="btn btn-primary">Select All</button>
|
||||
<button onClick={() => {
|
||||
this.api.deselectAll();
|
||||
}} className="btn btn-primary">Clear Selection</button>
|
||||
</span>
|
||||
<span style={{ float: "right" }}>
|
||||
Column API:
|
||||
<button onClick={() => {
|
||||
this.columnApi.setColumnVisible('country', false);
|
||||
}} className="btn btn-primary">Hide Country Column</button>
|
||||
<button onClick={() => {
|
||||
this.columnApi.setColumnVisible('country', 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" }}>
|
||||
<button onClick={this.onRefreshData} className="btn btn-primary">Refresh Data</button>
|
||||
</div>
|
||||
<div style={{ float: "right" }}>
|
||||
Filter API:
|
||||
<button onClick={this.invokeSkillsFilterMethod}
|
||||
className="btn btn-primary">Invoke Skills Filter Method
|
||||
</button>
|
||||
<button onClick={this.dobFilter} className="btn btn-primary">DOB equals to 01/01/2000
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: "inline-block", width: "100%", marginTop: 10, marginBottom: 10 }}>
|
||||
<div style={{ float: "left" }}>
|
||||
<label htmlFor="sideBarToggle">Show Side Bar </label>
|
||||
<input type="checkbox" id="sideBarToggle" onChange={this.onToggleSidebar} style={{ marginRight: 5 }} />
|
||||
</div>
|
||||
<div style={{ float: "right", marginLeft: 20 }}>
|
||||
<label htmlFor="quickFilter">Quick Filter: </label>
|
||||
<input type="text" id="quickFilter" onChange={this.onQuickFilterText} placeholder="Type text to filter..." />
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ height: 400, width: 900 }} className="ag-theme-balham">
|
||||
<AgGridReact
|
||||
// listening for events
|
||||
onGridReady={this.onGridReady}
|
||||
onRowSelected={this.onRowSelected}
|
||||
onCellClicked={this.onCellClicked}
|
||||
onModelUpdated={this.calculateRowCount}
|
||||
|
||||
// binding to simple properties
|
||||
sideBar={this.state.sideBar}
|
||||
quickFilterText={this.state.quickFilterText}
|
||||
|
||||
// binding to an object property
|
||||
icons={this.state.icons}
|
||||
|
||||
// binding to array properties
|
||||
rowData={this.state.rowData}
|
||||
|
||||
// register all modules (row model, csv/excel, row grouping etc)
|
||||
modules={AllModules}
|
||||
|
||||
// no binding, just providing hard coded strings for the properties
|
||||
// boolean properties will default to true if provided (ie suppressRowClickSelection => suppressRowClickSelection="true")
|
||||
suppressRowClickSelection
|
||||
rowSelection="multiple"
|
||||
groupHeaders
|
||||
|
||||
// setting grid wide date component
|
||||
dateComponentFramework={DateComponent}
|
||||
|
||||
// setting default column properties
|
||||
defaultColDef={{
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
filter: true,
|
||||
headerComponentFramework: SortableHeaderComponent,
|
||||
headerComponentParams: {
|
||||
menuIcon: 'fa-bars'
|
||||
}
|
||||
}}>
|
||||
<AgGridColumn headerName="#" width={40}
|
||||
checkboxSelection sortable={false} suppressMenu filter={false} pinned>
|
||||
</AgGridColumn>
|
||||
<AgGridColumn headerName="Employee" headerGroupComponentFramework={HeaderGroupComponent}>
|
||||
<AgGridColumn field="name" width={150}
|
||||
cellEditorFramework={NameCellEditor}
|
||||
enableRowGroup enablePivot pinned editable />
|
||||
<AgGridColumn field="country" width={150}
|
||||
cellRenderer={RichGridDeclarativeExample.countryCellRenderer}
|
||||
filterParams={{
|
||||
cellRenderer: RichGridDeclarativeExample.countryCellRenderer,
|
||||
cellHeight: 20
|
||||
}}
|
||||
enableRowGroup enablePivot pinned editable />
|
||||
<AgGridColumn field="dob" width={175} headerName="DOB" filter="agDateColumnFilter"
|
||||
pinned columnGroupShow="open"
|
||||
cellRenderer={RichGridDeclarativeExample.dateCellRenderer} />
|
||||
</AgGridColumn>
|
||||
<AgGridColumn headerName="IT Skills">
|
||||
<AgGridColumn field="skills" width={120} enableRowGroup enablePivot sortable={false}
|
||||
cellRendererFramework={SkillsCellRenderer}
|
||||
filterFramework={SkillsFilter} />
|
||||
<AgGridColumn field="proficiency" width={160} enableValue
|
||||
cellRendererFramework={ProficiencyCellRenderer}
|
||||
filterFramework={ProficiencyFilter} />
|
||||
</AgGridColumn>
|
||||
<AgGridColumn headerName="Contact">
|
||||
<AgGridColumn field="mobile" width={150} filter="text" />
|
||||
<AgGridColumn field="landline" width={150} filter="text" />
|
||||
<AgGridColumn field="address" width={500} filter="text" />
|
||||
</AgGridColumn>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 += ' ';
|
||||
@@ -5,8 +5,8 @@ import RefData from './RefData';
|
||||
export default class SkillsCellRenderer extends React.Component {
|
||||
|
||||
render() {
|
||||
var skills = [];
|
||||
var rowData = this.props.data;
|
||||
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}/>);
|
||||
@@ -42,8 +42,8 @@ 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) => {
|
||||
if (this.state[skill]) {
|
||||
@@ -56,16 +56,20 @@ export default class SkillsFilter extends React.Component {
|
||||
return passed;
|
||||
};
|
||||
|
||||
getModelAsString() {
|
||||
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);
|
||||
@@ -77,12 +81,12 @@ export default class SkillsFilter extends React.Component {
|
||||
|
||||
render() {
|
||||
|
||||
var skillsTemplates = [];
|
||||
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>
|
||||
@@ -98,7 +102,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}
|
||||
@@ -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'
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {AgGridReact} from "@ag-grid-community/react";
|
||||
import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
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: [
|
||||
{
|
||||
field: 'symbol'
|
||||
},
|
||||
{
|
||||
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-theme-balham">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.props.rowData}
|
||||
modules={AllModules}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// pull off row data changes
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
rowData: state.rowData
|
||||
}
|
||||
}
|
||||
)(GridComponent);
|
||||
@@ -0,0 +1,83 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
|
||||
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)} className="btn btn-primary">Set Currency to GBP</button>
|
||||
<button onClick={this.setCurrency.bind(this, '$', 1.29)} className="btn btn-primary">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);
|
||||
@@ -0,0 +1,45 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import FontContext from './fontContext'
|
||||
|
||||
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 (
|
||||
<FontContext.Consumer>
|
||||
{fontWeight => <span
|
||||
style={{fontWeight}}> {this.props.currencySymbol}{this.state.convertedValue}</span>}
|
||||
</FontContext.Consumer>
|
||||
);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{forwardRef: true} // must be supplied for react/redux when using AgGridReact
|
||||
)(PriceRenderer);
|
||||
@@ -1,14 +1,14 @@
|
||||
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";
|
||||
|
||||
import FontContext from './fontContext'
|
||||
|
||||
let store = createStore(gridData);
|
||||
|
||||
/*
|
||||
@@ -18,21 +18,17 @@ let store = createStore(gridData);
|
||||
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 }} />
|
||||
<h1>Simple Redux Example using Connected React Components</h1>
|
||||
<HeaderComponent/>
|
||||
<FontContext.Provider value="bold">
|
||||
<GridComponent/>
|
||||
</FontContext.Provider>
|
||||
</div>
|
||||
</Provider>
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
import React from "react";
|
||||
|
||||
export default React.createContext('normal');
|
||||
@@ -0,0 +1,14 @@
|
||||
export function updateRowData(rowData) {
|
||||
return {
|
||||
type: 'ROW_DATA_CHANGED',
|
||||
rowData
|
||||
}
|
||||
}
|
||||
|
||||
export function setCurrency(currencySymbol, exchangeRate) {
|
||||
return {
|
||||
type: 'CURRENCY_CHANGED',
|
||||
currencySymbol,
|
||||
exchangeRate
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
export default (state = {rowData: [], rowSelection: []}, action) => {
|
||||
export default (state = {rowData: [], currencySymbol: '£', exchangeRate: 1}, action) => {
|
||||
switch (action.type) {
|
||||
case 'ROW_DATA_CHANGED':
|
||||
return {
|
||||
...state,
|
||||
rowData: action.rowData,
|
||||
};
|
||||
case 'ROW_SELECTION_CHANGED':
|
||||
case 'CURRENCY_CHANGED':
|
||||
return {
|
||||
...state,
|
||||
rowSelection: action.rowSelection,
|
||||
currencySymbol: action.currencySymbol,
|
||||
exchangeRate: action.exchangeRate
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
34
src-examples/simpleReduxHooksExample/GridComponent.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import React, {useContext} from "react";
|
||||
import {Context} from "./store";
|
||||
import {AgGridReact} from "@ag-grid-community/react";
|
||||
import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
/*
|
||||
* This component serves to display the row data (provided by redux)
|
||||
*/
|
||||
export default function GridComponent() {
|
||||
const {store, dispatch} = useContext(Context);
|
||||
const {columnDefs, rowData} = store;
|
||||
|
||||
const onGridReady = (params) => {
|
||||
params.api.sizeColumnsToFit();
|
||||
};
|
||||
|
||||
// row data will be provided via redux on this.props.rowData
|
||||
return (
|
||||
<div style={{height: 400, width: 900, marginTop: 15}}
|
||||
className="ag-theme-balham">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={columnDefs}
|
||||
rowData={rowData}
|
||||
modules={AllModules}
|
||||
|
||||
defaultColDef={{filter: true}}
|
||||
|
||||
// events
|
||||
onGridReady={onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
18
src-examples/simpleReduxHooksExample/PriceEditor.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React, {useEffect, forwardRef, useImperativeHandle, useRef} from "react";
|
||||
|
||||
export default forwardRef((props, ref) => {
|
||||
const inputRef = useRef();
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
getValue: () => {
|
||||
return inputRef.current.value;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// https://github.com/facebook/react/issues/7835#issuecomment-395504863
|
||||
setTimeout(() => inputRef.current.focus(), 10)
|
||||
}, []);
|
||||
return <input type="text" ref={inputRef} defaultValue={props.value}/>;
|
||||
})
|
||||
18
src-examples/simpleReduxHooksExample/PriceFilter.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React, {forwardRef, useImperativeHandle, useRef} from "react";
|
||||
|
||||
export default forwardRef((props, ref) => {
|
||||
const inputRef = useRef();
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
isFilterActive() {
|
||||
return inputRef.current.value !== '';
|
||||
},
|
||||
|
||||
doesFilterPass: (params) => {
|
||||
return params.data.price.toString() === inputRef.current.value;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return <input type="text" ref={inputRef} onChange={() => props.filterChangedCallback()}/>;
|
||||
})
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class CurrencyRenderer extends Component {
|
||||
export default class PriceRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span style={this.props.style}>{this.props.value}</span>
|
||||
<span>{this.props.value}</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import React, {useReducer} from "react";
|
||||
import GridComponent from "./GridComponent";
|
||||
|
||||
import {Context, initialState, reducer} from "./store";
|
||||
|
||||
export default function SimpleReduxHookExample() {
|
||||
const [store, dispatch] = useReducer(reducer, initialState);
|
||||
|
||||
return (
|
||||
<Context.Provider value={{store, dispatch}}>
|
||||
<div>
|
||||
<h1>Simple Example using Hooks (with useContext and useReducer)</h1>
|
||||
<button onClick={() => dispatch({type: "SET_ROW_DATA"})} className="btn btn-primary">Populate Row Data</button>
|
||||
<GridComponent/>
|
||||
</div>
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
14
src-examples/simpleReduxHooksExample/gridDataActions.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
export function updateRowData(rowData) {
|
||||
return {
|
||||
type: 'ROW_DATA_CHANGED',
|
||||
rowData
|
||||
}
|
||||
}
|
||||
|
||||
export function setCurrency(currencySymbol, exchangeRate) {
|
||||
return {
|
||||
type: 'CURRENCY_CHANGED',
|
||||
currencySymbol,
|
||||
exchangeRate
|
||||
}
|
||||
}
|
||||
81
src-examples/simpleReduxHooksExample/store.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from "react";
|
||||
import PriceRenderer from "./PriceRenderer";
|
||||
import PriceEditor from "./PriceEditor";
|
||||
import PriceFilter from "./PriceFilter";
|
||||
|
||||
export const initialState = {
|
||||
rowData: [],
|
||||
columnDefs: [
|
||||
{
|
||||
field: 'symbol',
|
||||
editable: true
|
||||
},
|
||||
{
|
||||
field: 'price',
|
||||
cellClass: 'align-right',
|
||||
editable: true,
|
||||
cellEditorFramework: PriceEditor,
|
||||
filterFramework: PriceFilter,
|
||||
cellRendererFramework: PriceRenderer
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const reducer = (state = {rowData: []}, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_ROW_DATA':
|
||||
return {
|
||||
...state,
|
||||
rowData: createRowData()
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const Context = React.createContext();
|
||||
|
||||
|
||||
// for test data
|
||||
// the following methods are for creating dummy row data
|
||||
const createRowData = () => {
|
||||
let rowData = [];
|
||||
|
||||
for (let i = 0; i < 14; i++) {
|
||||
let newItem = createItem(rowData);
|
||||
rowData.push(newItem);
|
||||
}
|
||||
|
||||
return rowData;
|
||||
};
|
||||
|
||||
const createItem = (rowData) => {
|
||||
return {
|
||||
symbol: createUniqueRandomSymbol(rowData),
|
||||
price: Math.floor(Math.random() * 100)
|
||||
};
|
||||
};
|
||||
|
||||
// creates a unique symbol, eg 'ADG' or 'ZJD'
|
||||
const createUniqueRandomSymbol = (rowData) => {
|
||||
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;
|
||||
rowData.forEach(function (oldItem) {
|
||||
if (oldItem.symbol === symbol) {
|
||||
isUnique = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return symbol;
|
||||
};
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="dist/bundle.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../dist/react-large.js" charset="utf-8"></script>
|
||||
<!-- Example uses font awesome icons -->
|
||||
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
</head>
|
||||
@@ -3,9 +3,9 @@
|
||||
import ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import LargeGrid from './largeGrid.jsx';
|
||||
// is there a better way of doing this?
|
||||
import 'ag-grid-root/dist/styles/ag-grid.css';
|
||||
import 'ag-grid-root/dist/styles/theme-fresh.css';
|
||||
|
||||
import '@ag-grid-community/core/dist/styles/ag-grid.css';
|
||||
import '@ag-grid-community/core/dist/styles/ag-theme-balham.css';
|
||||
|
||||
// waiting for dom to load before booting react. we could alternatively
|
||||
// put the index.js reference at the end fo the index.html, but i prefer this way.
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
import {reactCellRendererFactory} from 'ag-grid-react';
|
||||
import React, {Component} from 'react';
|
||||
import SimpleCellRenderer from './simpleCellRenderer.jsx';
|
||||
import {AgGridReact} from '@ag-grid-community/react';
|
||||
|
||||
import {AgGridReact} from 'ag-grid-react';
|
||||
// for community features
|
||||
import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
// put this line in to use ag-Grid enterprise
|
||||
// import 'ag-grid-enterprise';
|
||||
// for enterprise features
|
||||
// import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
export default class MyApp extends React.Component {
|
||||
export default class MyApp extends Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -22,7 +23,7 @@ export default class MyApp extends React.Component {
|
||||
|
||||
createColumnNames() {
|
||||
// creates column names by iterating the alphabet twice, eg {'aa','ab','ac',.....'zz'}
|
||||
var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
|
||||
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
|
||||
this.columnNames = [];
|
||||
alphabet.forEach(letter1 => {
|
||||
alphabet.forEach(letter2 => {
|
||||
@@ -32,10 +33,10 @@ export default class MyApp extends React.Component {
|
||||
}
|
||||
|
||||
createRowData() {
|
||||
var rowData = [];
|
||||
const rowData = [];
|
||||
|
||||
for (var i = 0; i<1000; i++) {
|
||||
var item = {};
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const item = {};
|
||||
this.columnNames.forEach(colName => {
|
||||
item[colName] = '(' + colName.toUpperCase() + ',' + i + ')'
|
||||
});
|
||||
@@ -46,7 +47,7 @@ export default class MyApp extends React.Component {
|
||||
}
|
||||
|
||||
createColumnDefs() {
|
||||
var columnDefs = [];
|
||||
const columnDefs = [];
|
||||
|
||||
this.columnNames.forEach(colName => {
|
||||
columnDefs.push({
|
||||
@@ -62,8 +63,8 @@ export default class MyApp extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: '100%'}} className="ag-fresh">
|
||||
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} />
|
||||
<div style={{height: '100%'}} className="ag-theme-balham">
|
||||
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} modules={AllModules}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import {AgGridReact} from "@ag-grid-community/react";
|
||||
|
||||
import assign from "lodash/assign";
|
||||
import uniq from "lodash/uniq";
|
||||
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
class FxQuoteMatrix extends Component {
|
||||
constructor(props) {
|
||||
@@ -35,6 +34,7 @@ class FxQuoteMatrix extends Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.gridApi) {
|
||||
const newRowData = nextProps.rowData;
|
||||
|
||||
const updatedRows = [];
|
||||
@@ -54,22 +54,27 @@ class FxQuoteMatrix extends Component {
|
||||
|
||||
|
||||
this.gridApi.updateRowData({update: updatedRows});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 410, width: 800}}
|
||||
className="ag-fresh">
|
||||
className="ag-theme-balham">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
enableSorting="false"
|
||||
enableFilter="false"
|
||||
defaultColDef={{
|
||||
sortable: false,
|
||||
filter: false
|
||||
}}
|
||||
|
||||
// callbacks
|
||||
getRowNodeId={this.getRowNodeId}
|
||||
|
||||
modules={[ClientSideRowModelModule]}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
@@ -81,7 +86,7 @@ class FxQuoteMatrix extends Component {
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
rowData: state.fxData
|
||||
rowData: state ? state.fxData : null
|
||||
}
|
||||
}
|
||||
)(FxQuoteMatrix);
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import {AgGridReact} from "@ag-grid-community/react";
|
||||
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
import map from "lodash/map";
|
||||
import difference from "lodash/difference";
|
||||
@@ -23,22 +24,22 @@ export default class extends Component {
|
||||
{
|
||||
field: 'price',
|
||||
headerName: 'Price',
|
||||
cellFormatter: this.numberFormatter,
|
||||
cellRenderer: 'animateShowChange',
|
||||
valueFormatter: this.numberFormatter,
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellStyle: {'text-align': 'right'}
|
||||
},
|
||||
{
|
||||
field: 'bid',
|
||||
headerName: 'Bid',
|
||||
cellFormatter: this.numberFormatter,
|
||||
cellRenderer: 'animateShowChange',
|
||||
valueFormatter: this.numberFormatter,
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellStyle: {'text-align': 'right'}
|
||||
},
|
||||
{
|
||||
field: 'ask',
|
||||
headerName: 'Ask',
|
||||
cellFormatter: this.numberFormatter,
|
||||
cellRenderer: 'animateShowChange',
|
||||
valueFormatter: this.numberFormatter,
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellStyle: {'text-align': 'right'}
|
||||
}
|
||||
]
|
||||
@@ -151,13 +152,17 @@ export default class extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 410, width: 800}}
|
||||
className="ag-fresh">
|
||||
className="ag-theme-balham">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
enableSorting="true"
|
||||
defaultColDef={{
|
||||
sortable: true
|
||||
}}
|
||||
rowSelection="single"
|
||||
|
||||
modules={[ClientSideRowModelModule]}
|
||||
|
||||
// callbacks
|
||||
getRowNodeId={this.getRowNodeId}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, {Component} from "react";
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import {AgGridReact} from "@ag-grid-community/react";
|
||||
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
|
||||
|
||||
class TopMoversGrid extends Component {
|
||||
constructor(props) {
|
||||
@@ -17,24 +18,24 @@ class TopMoversGrid extends Component {
|
||||
field: 'last',
|
||||
headerName: 'Last',
|
||||
headerClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClass: 'align-right'
|
||||
},
|
||||
{
|
||||
field: 'net',
|
||||
headerName: 'Net',
|
||||
headerClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClass: 'align-right'
|
||||
},
|
||||
{
|
||||
field: 'pct_net_change',
|
||||
headerName: '% NC',
|
||||
headerClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClass: 'align-right',
|
||||
sort: 'desc',
|
||||
cellFormatter(params) {
|
||||
valueFormatter(params) {
|
||||
return params.value.toFixed(2)
|
||||
}
|
||||
},
|
||||
@@ -62,17 +63,21 @@ class TopMoversGrid extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 410, width: 400}}
|
||||
className="ag-fresh">
|
||||
className="ag-theme-balham">
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.props.rowData}
|
||||
enableSorting
|
||||
enableFilter="false"
|
||||
defaultColDef={{
|
||||
sortable: true,
|
||||
filter: false
|
||||
}}
|
||||
animateRows
|
||||
deltaRowDataMode
|
||||
getRowNodeId={this.getRowNodeId}
|
||||
|
||||
modules={[ClientSideRowModelModule]}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
@@ -84,7 +89,7 @@ class TopMoversGrid extends Component {
|
||||
export default connect(
|
||||
(state) => {
|
||||
return {
|
||||
rowData: state.fxTopMovers
|
||||
rowData: state ? state.fxTopMovers : null
|
||||
}
|
||||
}
|
||||
)(TopMoversGrid);
|
||||
@@ -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 = {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="dist/react-trader.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../dist/react-trader.js" charset="utf-8"></script>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
|
||||
@@ -5,12 +5,12 @@ import {render} from "react-dom";
|
||||
|
||||
import {Provider} from "react-redux";
|
||||
|
||||
import "ag-grid-root/dist/styles/ag-grid.css";
|
||||
import "ag-grid-root/dist/styles/theme-fresh.css";
|
||||
|
||||
import StoreService from './services/StoreService';
|
||||
import TraderDashboard from "./components/TraderDashboard.jsx";
|
||||
|
||||
import "@ag-grid-enterprise/all-modules/dist/styles/ag-grid.css";
|
||||
import "@ag-grid-enterprise/all-modules/dist/styles/ag-theme-balham.css";
|
||||
|
||||
let store = StoreService.STORE;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
@@ -120,7 +120,7 @@ const FX_DELTA_HEADERS = [
|
||||
field: 'last',
|
||||
headerName: 'Last',
|
||||
headerClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClass: 'align-right',
|
||||
width: 100
|
||||
},
|
||||
@@ -128,7 +128,7 @@ const FX_DELTA_HEADERS = [
|
||||
field: 'net',
|
||||
headerName: 'Net',
|
||||
headerClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClass: 'align-right',
|
||||
width: 90
|
||||
},
|
||||
@@ -145,7 +145,7 @@ const FX_DELTA_HEADERS = [
|
||||
headerName: symbol,
|
||||
width: 67,
|
||||
cellClass: 'align-right',
|
||||
cellRenderer: 'animateShowChange',
|
||||
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||
cellClassRules: {
|
||||
'fx-positive': 'x > 0.8',
|
||||
'fx-null': 'x === null',
|
||||
|
||||
103
src/App.jsx
@@ -1,103 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import "url-search-params-polyfill";
|
||||
|
||||
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 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 SimpleGridExample from "./floatingFilter/SimpleGridExample";
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let searchParams = new URLSearchParams(window.location.search);
|
||||
let fromDocs = searchParams.has("fromDocs");
|
||||
let example = searchParams.has("example") ? searchParams.get("example") : 'rich-grid';
|
||||
|
||||
this.state = {
|
||||
example,
|
||||
fromDocs
|
||||
};
|
||||
|
||||
this.setExample = this.setExample.bind(this);
|
||||
}
|
||||
|
||||
setExample(example) {
|
||||
this.setState({
|
||||
example
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
let header = null;
|
||||
if (!this.state.fromDocs) {
|
||||
header = (
|
||||
<ul className="nav nav-pills">
|
||||
<li role="presentation" className={this.state.example === 'rich-grid' ? 'active' : null} onClick={() => this.setExample("rich-grid")}><a href="#">Rich Grid Example</a></li>
|
||||
<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="#">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>
|
||||
</ul>)
|
||||
}
|
||||
|
||||
let example = null;
|
||||
switch (this.state.example) {
|
||||
case 'dynamic':
|
||||
example = <DynamicComponentsExample/>;
|
||||
break;
|
||||
case 'rich-dynamic':
|
||||
example = <RichComponentsExample/>;
|
||||
break;
|
||||
case 'editor':
|
||||
example = <EditorComponentsExample/>;
|
||||
break;
|
||||
case 'floating-row':
|
||||
example = <FloatingRowComponentExample/>;
|
||||
break;
|
||||
case 'full-width':
|
||||
example = <FullWidthComponentExample/>;
|
||||
break;
|
||||
case 'group-row':
|
||||
example = <GroupedRowInnerRendererComponentExample/>;
|
||||
break;
|
||||
case 'filter':
|
||||
example = <FilterComponentExample/>;
|
||||
break;
|
||||
case 'master-detail':
|
||||
example = <MasterDetailExample/>;
|
||||
break;
|
||||
case 'simple-redux':
|
||||
example = <SimpleReduxExample/>;
|
||||
break;
|
||||
case 'floating-filter':
|
||||
example = <SimpleGridExample/>;
|
||||
break;
|
||||
default:
|
||||
example = <RichGridExample/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{header}
|
||||
{example}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
@@ -1,19 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class ChildMessageRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.invokeParentMethod = this.invokeParentMethod.bind(this);
|
||||
}
|
||||
|
||||
invokeParentMethod() {
|
||||
this.props.context.componentParent.methodFromParent(`Row: ${this.props.node.rowIndex}, Col: ${this.props.colDef.headerName}`)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span><button style={{height: 20}} onClick={this.invokeParentMethod}>Invoke Parent</button></span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class CubeRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: this.valueSquared()
|
||||
};
|
||||
}
|
||||
|
||||
valueSquared() {
|
||||
return this.props.value * this.props.value * this.props.value;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>{this.state.value}</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class CurrencyRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
formatValueToCurrency(currency, value) {
|
||||
return `${currency}${value}`
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>{this.formatValueToCurrency('EUR', this.props.value)}</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import SquareRenderer from "./SquareRenderer";
|
||||
import CubeRenderer from "./CubeRenderer";
|
||||
import ParamsRenderer from "./ParamsRenderer";
|
||||
import CurrencyRenderer from "./CurrencyRenderer";
|
||||
import ChildMessageRenderer from "./ChildMessageRenderer";
|
||||
|
||||
export default class DynamicComponentsExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
gridOptions: {
|
||||
context: {
|
||||
componentParent: this
|
||||
}
|
||||
},
|
||||
|
||||
rowData: this.createRowData(),
|
||||
|
||||
columnDefs: this.createColumnDefs()
|
||||
};
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
this.refreshRowData = this.refreshRowData.bind(this);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
}
|
||||
|
||||
onCellValueChanged($event) {
|
||||
this.gridApi.refreshCells([$event.node],["cube"]);
|
||||
}
|
||||
|
||||
methodFromParent(cell) {
|
||||
alert(`Parent Component Method from ${cell}!`);
|
||||
}
|
||||
|
||||
createColumnDefs() {
|
||||
return [
|
||||
{headerName: "Row", field: "row", width: 100},
|
||||
{
|
||||
headerName: "Square",
|
||||
field: "value",
|
||||
cellRendererFramework: SquareRenderer,
|
||||
editable:true,
|
||||
colId: "square",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
headerName: "Cube",
|
||||
field: "value",
|
||||
cellRendererFramework: CubeRenderer,
|
||||
colId: "cube",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
headerName: "Row Params",
|
||||
field: "row",
|
||||
cellRendererFramework: ParamsRenderer,
|
||||
colId: "params",
|
||||
width: 215
|
||||
},
|
||||
{
|
||||
headerName: "Currency",
|
||||
field: "currency",
|
||||
cellRendererFramework: CurrencyRenderer,
|
||||
colId: "params",
|
||||
width: 135
|
||||
},
|
||||
{
|
||||
headerName: "Child/Parent",
|
||||
field: "value",
|
||||
cellRendererFramework: ChildMessageRenderer,
|
||||
colId: "params",
|
||||
width: 120
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
refreshRowData() {
|
||||
let rowData = this.createRowData();
|
||||
this.gridApi.setRowData(rowData);
|
||||
}
|
||||
|
||||
createRowData() {
|
||||
let rowData = [];
|
||||
|
||||
for (let i = 0; i < 15; i++) {
|
||||
rowData.push({
|
||||
row: "Row " + i,
|
||||
value: i,
|
||||
currency: 1 + Number(Math.random()).toFixed(2)
|
||||
});
|
||||
}
|
||||
|
||||
return rowData;
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 400, width: 945}}
|
||||
className="ag-fresh">
|
||||
<h1>Dynamic React Component Example</h1>
|
||||
<button onClick={this.refreshRowData}>Refresh Data</button>
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.state.rowData}
|
||||
gridOptions={this.state.gridOptions}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class ParamsRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>Field: {this.props.colDef.field}, Value: {this.props.value}</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class SquareRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: this.valueSquared()
|
||||
};
|
||||
}
|
||||
|
||||
valueSquared() {
|
||||
return this.props.value * this.props.value;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>{this.state.value}</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import MoodRenderer from "./MoodRenderer";
|
||||
import MoodEditor from "./MoodEditor";
|
||||
import NumericEditor from "./NumericEditor";
|
||||
|
||||
export default class EditorComponentsExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rowData: this.createRowData(),
|
||||
columnDefs: this.createColumnDefs()
|
||||
};
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
}
|
||||
|
||||
createColumnDefs() {
|
||||
return [
|
||||
{headerName: "Name", field: "name", width: 300},
|
||||
{
|
||||
headerName: "Mood",
|
||||
field: "mood",
|
||||
cellRendererFramework: MoodRenderer,
|
||||
cellEditorFramework: MoodEditor,
|
||||
editable: true,
|
||||
width: 250
|
||||
},
|
||||
{
|
||||
headerName: "Numeric",
|
||||
field: "number",
|
||||
cellEditorFramework: NumericEditor,
|
||||
editable: true,
|
||||
width: 250
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
createRowData() {
|
||||
return [
|
||||
{name: "Bob", mood: "Happy", number: 10},
|
||||
{name: "Harry", mood: "Sad", number: 3},
|
||||
{name: "Sally", mood: "Happy", number: 20},
|
||||
{name: "Mary", mood: "Sad", number: 5},
|
||||
{name: "John", mood: "Happy", number: 15},
|
||||
{name: "Jack", mood: "Happy", number: 25},
|
||||
{name: "Sue", mood: "Sad", number: 43},
|
||||
{name: "Sean", mood: "Sad", number: 1335},
|
||||
{name: "Niall", mood: "Happy", number: 2},
|
||||
{name: "Alberto", mood: "Happy", number: 123},
|
||||
{name: "Fred", mood: "Sad", number: 532},
|
||||
{name: "Jenny", mood: "Happy", number: 34},
|
||||
{name: "Larry", mood: "Happy", number: 13},
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 400, width: 945}}
|
||||
className="ag-fresh">
|
||||
<h1>Cell Editor Component Example</h1>
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.state.rowData}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,107 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
export default class MoodEditor extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onHappyClick = this.onHappyClick.bind(this);
|
||||
this.onSadClick = this.onSadClick.bind(this);
|
||||
|
||||
this.state = {
|
||||
happy: false
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.setHappy(this.props.value === "Happy");
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
focus() {
|
||||
setTimeout(() => {
|
||||
let container = ReactDOM.findDOMNode(this.refs.container);
|
||||
if (container) {
|
||||
container.focus();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.state.happy ? "Happy" : "Sad";
|
||||
}
|
||||
|
||||
isPopup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
setHappy(happy) {
|
||||
this.setState({
|
||||
happy
|
||||
});
|
||||
}
|
||||
|
||||
onHappyClick() {
|
||||
this.setState({
|
||||
happy: true
|
||||
},
|
||||
() => this.props.api.stopEditing()
|
||||
);
|
||||
}
|
||||
|
||||
onSadClick() {
|
||||
this.setState({
|
||||
happy: false
|
||||
},
|
||||
() => this.props.api.stopEditing()
|
||||
);
|
||||
}
|
||||
|
||||
toggleMood() {
|
||||
this.setHappy(!this.state.happy);
|
||||
}
|
||||
|
||||
render() {
|
||||
let mood = {
|
||||
borderRadius: 15,
|
||||
border: "1px solid grey",
|
||||
background: "#e6e6e6",
|
||||
padding: 15,
|
||||
textAlign: "center",
|
||||
display: "inline-block",
|
||||
// outline: "none"
|
||||
};
|
||||
|
||||
let unselected = {
|
||||
paddingLleft: 10,
|
||||
paddingRight: 10,
|
||||
border: "1px solid transparent",
|
||||
padding: 4
|
||||
};
|
||||
|
||||
let selected = {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
border: "1px solid lightgreen",
|
||||
padding: 4
|
||||
};
|
||||
|
||||
let happyStyle = this.state.value === 'Happy' ? selected : unselected;
|
||||
let sadStyle = this.state.value !== 'Happy' ? selected : unselected;
|
||||
|
||||
return (
|
||||
<div ref="container"
|
||||
style={mood}>
|
||||
<img src="images/smiley.png" onClick={this.onHappyClick} style={happyStyle}/>
|
||||
<img src="images/smiley-sad.png" onClick={this.onSadClick} style={sadStyle}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
export default class MoodRenderer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.setMood(this.props.value)
|
||||
}
|
||||
|
||||
refresh(params) {
|
||||
this.setMood(params.value);
|
||||
}
|
||||
|
||||
setMood(mood) {
|
||||
this.setState({
|
||||
imgForMood: mood === 'Happy' ? 'images/smiley.png' : 'images/smiley-sad.png'
|
||||
})
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<img width="20px" src={this.state.imgForMood}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
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);
|
||||
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
focus() {
|
||||
setTimeout(() => {
|
||||
let container = ReactDOM.findDOMNode(this.refs.input);
|
||||
if (container) {
|
||||
container.focus();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.state.value;
|
||||
}
|
||||
|
||||
isCancelBeforeStart() {
|
||||
return this.cancelBeforeStart;
|
||||
}
|
||||
|
||||
// will reject the number if it greater than 1,000,000
|
||||
// not very practical, but demonstrates the method.
|
||||
isCancelAfterEnd() {
|
||||
return this.state.value > 1000000;
|
||||
};
|
||||
|
||||
onKeyDown(event) {
|
||||
if (!this.isKeyPressedNumeric(event)) {
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
handleChange(event) {
|
||||
this.setState({value: event.target.value});
|
||||
}
|
||||
|
||||
getCharCodeFromEvent(event) {
|
||||
event = event || window.event;
|
||||
return (typeof event.which === "undefined") ? event.keyCode : event.which;
|
||||
}
|
||||
|
||||
isCharNumeric(charStr) {
|
||||
return !!/\d/.test(charStr);
|
||||
}
|
||||
|
||||
isKeyPressedNumeric(event) {
|
||||
const charCode = this.getCharCodeFromEvent(event);
|
||||
const charStr = event.key ? event.key : String.fromCharCode(charCode);
|
||||
return this.isCharNumeric(charStr);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input ref="input"
|
||||
value={this.state.value}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
|
||||
import "ag-grid-enterprise";
|
||||
|
||||
import PartialMatchFilter from "./PartialMatchFilter";
|
||||
|
||||
export default class FilterComponentExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
gridOptions: {},
|
||||
|
||||
rowData: this.createRowData(),
|
||||
columnDefs: this.createColumnDefs(),
|
||||
};
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
this.onClicked = this.onClicked.bind(this);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
}
|
||||
|
||||
onClicked() {
|
||||
this.gridApi.getFilterInstance("name").getFrameworkComponentInstance().componentMethod("Hello World!");
|
||||
}
|
||||
|
||||
createColumnDefs() {
|
||||
return [
|
||||
{headerName: "Row", field: "row", width: 400},
|
||||
{
|
||||
headerName: "Filter Component",
|
||||
field: "name",
|
||||
filterFramework: PartialMatchFilter,
|
||||
width: 400,
|
||||
menuTabs:['filterMenuTab']
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
createRowData() {
|
||||
return [
|
||||
{"row": "Row 1", "name": "Michael Phelps"},
|
||||
{"row": "Row 2", "name": "Natalie Coughlin"},
|
||||
{"row": "Row 3", "name": "Aleksey Nemov"},
|
||||
{"row": "Row 4", "name": "Alicia Coutts"},
|
||||
{"row": "Row 5", "name": "Missy Franklin"},
|
||||
{"row": "Row 6", "name": "Ryan Lochte"},
|
||||
{"row": "Row 7", "name": "Allison Schmitt"},
|
||||
{"row": "Row 8", "name": "Natalie Coughlin"},
|
||||
{"row": "Row 9", "name": "Ian Thorpe"},
|
||||
{"row": "Row 10", "name": "Bob Mill"},
|
||||
{"row": "Row 11", "name": "Willy Walsh"},
|
||||
{"row": "Row 12", "name": "Sarah McCoy"},
|
||||
{"row": "Row 13", "name": "Jane Jack"},
|
||||
{"row": "Row 14", "name": "Tina Wills"}
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 400, width: 945}}
|
||||
className="ag-fresh">
|
||||
<h1>Filter Component Example</h1>
|
||||
<button style={{marginBottom: 10}} onClick={this.onClicked}>Filter Instance Method</button>
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.state.rowData}
|
||||
|
||||
enableFilter
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,70 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
export default class PartialMatchFilter extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
text: ''
|
||||
}
|
||||
this.valueGetter = this.props.valueGetter;
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
}
|
||||
|
||||
isFilterActive() {
|
||||
return this.state.text !== null && this.state.text !== undefined && this.state.text !== '';
|
||||
}
|
||||
|
||||
doesFilterPass(params) {
|
||||
return this.state.text.toLowerCase()
|
||||
.split(" ")
|
||||
.every((filterWord) => {
|
||||
return this.valueGetter(params.node).toString().toLowerCase().indexOf(filterWord) >= 0;
|
||||
});
|
||||
}
|
||||
|
||||
getModel() {
|
||||
return {value: this.state.text};
|
||||
}
|
||||
|
||||
setModel(model) {
|
||||
this.state.text = model ? model.value : '';
|
||||
}
|
||||
|
||||
afterGuiAttached(params) {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
focus() {
|
||||
setTimeout(() => {
|
||||
let container = ReactDOM.findDOMNode(this.refs.input);
|
||||
if (container) {
|
||||
container.focus();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentMethod(message) {
|
||||
alert(`Alert from PartialMatchFilterComponent ${message}`);
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
let newValue = event.target.value;
|
||||
if (this.state.text !== newValue) {
|
||||
this.setState({
|
||||
text: newValue
|
||||
}, () => {
|
||||
this.props.filterChangedCallback();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>Filter: <input style={{height: "20px"}} ref="input" value={this.state.text} onChange={this.onChange}/></span>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import FloatingFilter from "./floatingFilter";
|
||||
|
||||
export default class 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 containerStyle = {
|
||||
height: 115,
|
||||
width: 500
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={containerStyle} className="ag-fresh">
|
||||
<h1>Simple ag-Grid React Example</h1>
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.state.rowData}
|
||||
|
||||
floatingFilter={true}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
export default class FloatingFilter extends Component {
|
||||
constructor(props) {
|
||||
super();
|
||||
this.state = {
|
||||
parentModel: null
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
let that = this;
|
||||
let options = this.state.parentModel.map ((item, i)=>{
|
||||
let that = this;
|
||||
let removeMeListener = ()=>{
|
||||
this.remove(item)
|
||||
}
|
||||
let removeMeElement = <a onClick={removeMeListener}>[x]</a>;
|
||||
return <span key={i}>{item}{removeMeElement}</span>;
|
||||
});
|
||||
|
||||
return <div>{options}</div>;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import {AgGridReact} from "ag-grid-react";
|
||||
import StyledRenderer from "./StyledRenderer";
|
||||
|
||||
export default class FloatingRowComponentExample extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
gridOptions: {},
|
||||
|
||||
rowData: this.createRowData(),
|
||||
columnDefs: this.createColumnDefs(),
|
||||
|
||||
pinnedTopRowData: [{row: "Top Row", number: "Top Number"}],
|
||||
pinnedBottomRowData: [{row: "Bottom Row", number: "Bottom Number"}]
|
||||
};
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.columnApi = params.columnApi;
|
||||
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
}
|
||||
|
||||
createColumnDefs() {
|
||||
return [
|
||||
{
|
||||
headerName: "Row",
|
||||
field: "row",
|
||||
width: 400,
|
||||
floatingCellRendererFramework: StyledRenderer,
|
||||
floatingCellRendererParams: {
|
||||
style: {'fontWeight': 'bold'}
|
||||
}
|
||||
},
|
||||
{
|
||||
headerName: "Number",
|
||||
field: "number",
|
||||
width: 399,
|
||||
floatingCellRendererFramework: StyledRenderer,
|
||||
floatingCellRendererParams: {
|
||||
style: {'fontStyle': 'italic'}
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
createRowData() {
|
||||
let rowData = [];
|
||||
|
||||
for (let i = 0; i < 15; i++) {
|
||||
rowData.push({
|
||||
row: "Rou " + i,
|
||||
number: Math.round(Math.random() * 100)
|
||||
});
|
||||
}
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{height: 400, width: 945}}
|
||||
className="ag-fresh">
|
||||
<h1>Pinned Row Renderer Example</h1>
|
||||
<AgGridReact
|
||||
// properties
|
||||
columnDefs={this.state.columnDefs}
|
||||
rowData={this.state.rowData}
|
||||
|
||||
pinnedTopRowData={this.state.pinnedTopRowData}
|
||||
pinnedBottomRowData={this.state.pinnedBottomRowData}
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||