Compare commits
106 Commits
react-fibe
...
b22.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d540eea26d | ||
|
|
86c353eaa9 | ||
|
|
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 |
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
/dist
|
/dist
|
||||||
|
package-lock.json
|
||||||
17
README.md
@@ -1,29 +1,18 @@
|
|||||||
|
|
||||||
ag-Grid React Example
|
ag-Grid React Example
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Examples of running ag-Grid inside React application.
|
## Examples
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
1. standard - shows a typical grid demonstrating many ag-Grid features
|
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
|
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
|
Building
|
||||||
==============
|
==============
|
||||||
|
|
||||||
To build:
|
To build:
|
||||||
- `npm install`
|
- `npm install`
|
||||||
- `npm install webpack -g`
|
|
||||||
- `npm run examples`, `npm run large` or `npm run trader`
|
- `npm run examples`, `npm run large` or `npm run trader`
|
||||||
- navigate to localhost:8080
|
- 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,
|
||||||
|
}
|
||||||
|
};
|
||||||
8618
olympicWinners.json
82
package.json
@@ -1,30 +1,30 @@
|
|||||||
{
|
{
|
||||||
"name": "ag-grid-react-example",
|
"name": "ag-grid-react-example",
|
||||||
"version": "13.2.0",
|
"version": "22.1.1",
|
||||||
"description": "Example Reach applicaiton using ag-Grid.",
|
"description": "Example Reach applicaiton using ag-Grid.",
|
||||||
"main": "dist/ag-grid-react-example.js",
|
"main": "dist/ag-grid-react-example.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"trader": "webpack-dev-server --content-base src-trader-dashboard/ --config webpack.config.trader.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/ --config webpack.config.examples.js --progress --colors --hot --inline",
|
"examples": "webpack-dev-server --content-base src-examples/ --config config/webpack.config.examples.js --mode development --open",
|
||||||
"large": "webpack-dev-server --config webpack.config.large.js --progress --colors --hot --inline",
|
"large": "webpack-dev-server --content-base src-large-data/ --config config/webpack.config.large.js --mode development --open",
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"mkdirs": "mkdirp dist/trader/dist dist/examples/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-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",
|
"copy": "npm run copy-examples && npm run copy-trader",
|
||||||
"build-large": "webpack --config webpack.config.large.js --progress --profile --bail",
|
"build-large": "webpack --config config/webpack.config.large.js --progress --profile --bail",
|
||||||
"build-examples": "webpack --config webpack.config.examples.js --progress --profile --bail",
|
"build-examples": "webpack --config config/webpack.config.examples.js --progress --profile --bail",
|
||||||
"build-dashboard": "webpack --config webpack.config.trader.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-all": "npm run build-examples && npm run build-dashboard",
|
||||||
"build": "npm run clean && npm run mkdirs && npm run build-all && npm run copy",
|
"build": "npm run clean && npm run mkdirs && npm run build-all && npm run copy",
|
||||||
"copy-to-docs": "ncp dist/examples ../ag-grid-docs/src/framework-examples/react-examples/examples && ncp dist/trader ../ag-grid-docs/src/framework-examples/react-examples/trader",
|
"start": "npm run examples",
|
||||||
"build-to-docs": "npm run build && npm run copy-to-docs",
|
"test": "./ts-tests/runTsTests.sh"
|
||||||
"start": "npm run examples"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ag-grid/ag-grid-react-example.git"
|
"url": "https://github.com/ag-grid/ag-grid-react-example.git"
|
||||||
},
|
},
|
||||||
|
"private": true,
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"grid",
|
"grid",
|
||||||
@@ -38,39 +38,39 @@
|
|||||||
},
|
},
|
||||||
"homepage": "http://www.ag-grid.com/",
|
"homepage": "http://www.ag-grid.com/",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "6.24.x",
|
"@ag-grid-community/core": "~22.1.1",
|
||||||
"babel-loader": "6.4.x",
|
"@babel/core": "7.4.4",
|
||||||
"babel-preset-es2015": "6.24.x",
|
"@babel/plugin-proposal-class-properties": "7.4.4",
|
||||||
"babel-preset-react": "6.24.x",
|
"@babel/plugin-proposal-function-bind": "7.2.0",
|
||||||
"babel-preset-stage-0": "6.24.x",
|
"@babel/preset-env": "7.4.4",
|
||||||
"babel-preset-stage-1": "6.24.x",
|
"@babel/preset-react": "7.0.0",
|
||||||
"css-loader": "0.23.x",
|
"@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",
|
"mkdirp": "0.5.1",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"prop-types": "15.5.x",
|
"prop-types": "15.7.2",
|
||||||
"rimraf": "2.5.x",
|
"rimraf": "2.6.3",
|
||||||
"style-loader": "0.13.x",
|
"style-loader": "0.23.1",
|
||||||
"webpack": "1.12.x",
|
"typescript": "3.4.5",
|
||||||
"webpack-dev-server": "1.14.x",
|
"webpack": "4.31.0",
|
||||||
"gulp": "3.9.x",
|
"webpack-cli": "3.3.2",
|
||||||
"gulp-typescript": "3.1.x",
|
"webpack-dev-server": "3.4.1"
|
||||||
"merge2": "1.0.x",
|
|
||||||
"typescript": "2.3.x"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ag-grid": "13.2.x",
|
"@ag-grid-enterprise/all-modules": "~22.1.1",
|
||||||
"ag-grid-enterprise": "13.2.x",
|
"@ag-grid-community/react": "~22.1.1",
|
||||||
"ag-grid-react": "13.2.x",
|
"bootstrap": "4.3.1",
|
||||||
"bootstrap": "3.3.7",
|
|
||||||
"d3": "4.9.1",
|
"d3": "4.9.1",
|
||||||
"file-loader": "0.11.1",
|
"lodash": "4.17.11",
|
||||||
"lodash": "4.17.4",
|
"react": "16.8.6",
|
||||||
"react": "15.6.x",
|
"react-dom": "16.8.6",
|
||||||
"react-dom": "15.6.x",
|
"react-redux": "7.0.3",
|
||||||
"react-dom-factories": "1.0.0",
|
"react-router-dom": "5.0.0",
|
||||||
"react-redux": "5.0.x",
|
"redux": "4.0.1"
|
||||||
"react-router-dom": "4.2.x",
|
|
||||||
"redux": "3.6.x",
|
|
||||||
"url-search-params-polyfill": "1.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import React, {PropTypes} from 'react'
|
import React from 'react'
|
||||||
import {Route, Link} from 'react-router-dom'
|
import * as PropTypes from 'prop-types';
|
||||||
|
import {Link, Route} from 'react-router-dom'
|
||||||
|
|
||||||
// for bootstrap li active functionality
|
// for bootstrap li active functionality
|
||||||
export default function NavItem({children, to, exact}) {
|
export default function NavItem({children, to, exact}) {
|
||||||
return (
|
return (
|
||||||
<Route path={to} exact={exact} children={({match}) => (
|
<Route path={to} exact={exact} children={({match}) => (
|
||||||
<li className={match ? 'active' : null}>
|
<li className="nav-item">
|
||||||
<Link to={to}>{children}</Link>
|
<Link className={match ? 'nav-link active' : 'nav-link'} to={to}>{children}</Link>
|
||||||
</li>
|
</li>
|
||||||
)}/>
|
)}/>
|
||||||
)
|
)
|
||||||
|
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>
|
<head>
|
||||||
<meta charset="utf-8">
|
<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 -->
|
<!-- Example uses font awesome icons -->
|
||||||
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||||||
|
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
line-height: 1
|
line-height: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
div.card-body > a {
|
div.card-body > a {
|
||||||
margin-top: 5px
|
margin-top: 5px
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,14 @@ import React from "react";
|
|||||||
import {render} from "react-dom";
|
import {render} from "react-dom";
|
||||||
import {BrowserRouter} from "react-router-dom";
|
import {BrowserRouter} from "react-router-dom";
|
||||||
|
|
||||||
import "ag-grid-root/dist/styles/ag-grid.css";
|
import "@ag-grid-enterprise/all-modules/dist/styles/ag-grid.css";
|
||||||
import "ag-grid-root/dist/styles/theme-fresh.css";
|
import "@ag-grid-enterprise/all-modules/dist/styles/ag-theme-balham.css";
|
||||||
import "../node_modules/bootstrap/dist/css/bootstrap.css";
|
import "../node_modules/bootstrap/dist/css/bootstrap.css";
|
||||||
|
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|
||||||
// only required when using enterprise features
|
// only required when using enterprise features
|
||||||
// import {LicenseManager} from "ag-grid-enterprise/main";
|
// import {LicenseManager} from "@ag-grid-enterprise/all-modules";
|
||||||
// LicenseManager.setLicenseKey("<your license key>");
|
// LicenseManager.setLicenseKey("<your license key>");
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@@ -37,7 +37,7 @@ export default class DateComponent extends React.Component {
|
|||||||
width: '30px'
|
width: '30px'
|
||||||
};
|
};
|
||||||
let yyyyStyle = {
|
let yyyyStyle = {
|
||||||
width: '60px'
|
width: '40px'
|
||||||
};
|
};
|
||||||
let resetStyle = {
|
let resetStyle = {
|
||||||
padding: '2px',
|
padding: '2px',
|
||||||
@@ -51,11 +51,11 @@ export default class DateComponent extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div style={filterStyle}>
|
<div style={filterStyle}>
|
||||||
<span style={resetStyle} onClick={this.resetDate.bind(this)}>x</span>
|
<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"/>/
|
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"/>/
|
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"/>
|
value={this.state.textBoxes.yyyy} maxLength="4"/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -41,16 +41,20 @@ export default class ProficiencyFilter extends React.Component {
|
|||||||
this.setState(newState, this.props.filterChangedCallback);
|
this.setState(newState, this.props.filterChangedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getModel() {
|
getModel() {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setModel(model) {
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
PROFICIENCY_NAMES.forEach((name) => {
|
PROFICIENCY_NAMES.forEach((name) => {
|
||||||
const selected = this.state.selected === name;
|
const selected = this.state.selected === name;
|
||||||
rows.push(
|
rows.push(
|
||||||
<div key={name}>
|
<div key={name} style={{marginTop: 3}}>
|
||||||
<label style={{paddingLeft: 4}}>
|
<label style={{paddingLeft: 4}}>
|
||||||
<input type="radio" checked={selected} name={Math.random()}
|
<input type="radio" checked={selected} name={Math.random()}
|
||||||
onChange={this.onButtonPressed.bind(this, name)}/>
|
onChange={this.onButtonPressed.bind(this, name)}/>
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
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-remove"/>',
|
||||||
|
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 = () => {
|
||||||
|
let skillsFilter = this.api.getFilterInstance('skills');
|
||||||
|
let componentInstance = skillsFilter.getFrameworkComponentInstance();
|
||||||
|
componentInstance.helloFromSkillsFilter();
|
||||||
|
};
|
||||||
|
|
||||||
|
dobFilter = () => {
|
||||||
|
let dateFilterComponent = this.api.getFilterInstance('dob');
|
||||||
|
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={30}
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ export default class SkillsFilter extends React.Component {
|
|||||||
return passed;
|
return passed;
|
||||||
};
|
};
|
||||||
|
|
||||||
getModel() {
|
getModelAsString() {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,6 @@ export default class SkillsFilter extends React.Component {
|
|||||||
|
|
||||||
const skillsTemplates = [];
|
const skillsTemplates = [];
|
||||||
RefData.IT_SKILLS.forEach((skill, index) => {
|
RefData.IT_SKILLS.forEach((skill, index) => {
|
||||||
|
|
||||||
const skillName = RefData.IT_SKILLS_NAMES[index];
|
const skillName = RefData.IT_SKILLS_NAMES[index];
|
||||||
const template = (
|
const template = (
|
||||||
<label key={skill}
|
<label key={skill}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
|
|
||||||
import {AgGridReact} from "ag-grid-react";
|
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
import {AgGridReact} from "@ag-grid-community/react";
|
||||||
|
import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||||
|
|
||||||
import PriceRenderer from "./PriceRenderer";
|
import PriceRenderer from "./PriceRenderer";
|
||||||
|
|
||||||
@@ -14,8 +14,14 @@ class GridComponent extends Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
{headerName: 'Symbol', field: 'symbol'},
|
{
|
||||||
{headerName: 'Price', field: 'price', cellClass: 'align-right', cellRendererFramework: PriceRenderer}
|
field: 'symbol'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'price',
|
||||||
|
cellClass: 'align-right',
|
||||||
|
cellRendererFramework: PriceRenderer
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,11 +39,12 @@ class GridComponent extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{height: 400, width: 900, marginTop: 15}}
|
<div style={{height: 400, width: 900, marginTop: 15}}
|
||||||
className="ag-fresh">
|
className="ag-theme-balham">
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
// properties
|
// properties
|
||||||
columnDefs={this.state.columnDefs}
|
columnDefs={this.state.columnDefs}
|
||||||
rowData={this.props.rowData}
|
rowData={this.props.rowData}
|
||||||
|
modules={AllModules}
|
||||||
|
|
||||||
// events
|
// events
|
||||||
onGridReady={this.onGridReady}>
|
onGridReady={this.onGridReady}>
|
||||||
@@ -54,4 +61,4 @@ export default connect(
|
|||||||
rowData: state.rowData
|
rowData: state.rowData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)(GridComponent);
|
)(GridComponent);
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
// take this line out if you do not want to use ag-Grid-Enterprise
|
|
||||||
import "ag-grid-enterprise";
|
|
||||||
|
|
||||||
import {setCurrency, updateRowData} from "./gridDataActions";
|
import {setCurrency, updateRowData} from "./gridDataActions";
|
||||||
|
|
||||||
@@ -25,8 +23,8 @@ class HeaderComponent extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{marginTop: 15}}>
|
<div style={{marginTop: 15}}>
|
||||||
<button onClick={this.setCurrency.bind(this, '£', 1)}>Set Currency to GBP</button>
|
<button onClick={this.setCurrency.bind(this, '£', 1)} className="btn btn-primary">Set Currency to GBP</button>
|
||||||
<button onClick={this.setCurrency.bind(this, '$', 1.29)}>Set Currency to USD</button>
|
<button onClick={this.setCurrency.bind(this, '$', 1.29)} className="btn btn-primary">Set Currency to USD</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -82,4 +80,4 @@ export default connect(
|
|||||||
rowData: state.rowData
|
rowData: state.rowData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)(HeaderComponent);
|
)(HeaderComponent);
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
|
||||||
|
import FontContext from './fontContext'
|
||||||
|
|
||||||
class PriceRenderer extends Component {
|
class PriceRenderer extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -18,7 +20,10 @@ class PriceRenderer extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<span>{this.props.currencySymbol}{this.state.convertedValue}</span>
|
<FontContext.Consumer>
|
||||||
|
{fontWeight => <span
|
||||||
|
style={{fontWeight}}> {this.props.currencySymbol}{this.state.convertedValue}</span>}
|
||||||
|
</FontContext.Consumer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,5 +38,8 @@ export default connect(
|
|||||||
currencySymbol: state.currencySymbol,
|
currencySymbol: state.currencySymbol,
|
||||||
exchangeRate: state.exchangeRate
|
exchangeRate: state.exchangeRate
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)(PriceRenderer);
|
null,
|
||||||
|
null,
|
||||||
|
{forwardRef: true} // must be supplied for react/redux when using AgGridReact
|
||||||
|
)(PriceRenderer);
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Provider} from "react-redux";
|
import {Provider} from "react-redux";
|
||||||
import {createStore} from "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 HeaderComponent from "./HeaderComponent";
|
||||||
import GridComponent from "./GridComponent";
|
import GridComponent from "./GridComponent";
|
||||||
|
|
||||||
import gridData from "./gridDataReducer";
|
import gridData from "./gridDataReducer";
|
||||||
|
|
||||||
|
import FontContext from './fontContext'
|
||||||
|
|
||||||
let store = createStore(gridData);
|
let store = createStore(gridData);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -25,8 +25,10 @@ export default class SimpleReduxExample extends Component {
|
|||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<div>
|
<div>
|
||||||
<h1>Simple Redux Example using Connected React Components</h1>
|
<h1>Simple Redux Example using Connected React Components</h1>
|
||||||
<HeaderComponent />
|
<HeaderComponent/>
|
||||||
<GridComponent />
|
<FontContext.Provider value="bold">
|
||||||
|
<GridComponent/>
|
||||||
|
</FontContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
</Provider>
|
</Provider>
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default React.createContext('normal');
|
||||||
@@ -4,6 +4,7 @@ export function updateRowData(rowData) {
|
|||||||
rowData
|
rowData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrency(currencySymbol, exchangeRate) {
|
export function setCurrency(currencySymbol, exchangeRate) {
|
||||||
return {
|
return {
|
||||||
type: 'CURRENCY_CHANGED',
|
type: 'CURRENCY_CHANGED',
|
||||||
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";
|
import React, {Component} from "react";
|
||||||
|
|
||||||
export default class CurrencyRenderer extends Component {
|
export default class PriceRenderer extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
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>
|
<head>
|
||||||
<meta charset="utf-8">
|
<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 -->
|
<!-- Example uses font awesome icons -->
|
||||||
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import LargeGrid from './largeGrid.jsx';
|
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-community/core/dist/styles/ag-grid.css';
|
||||||
import 'ag-grid-root/dist/styles/theme-fresh.css';
|
import '@ag-grid-community/core/dist/styles/ag-theme-fresh.css';
|
||||||
|
|
||||||
// waiting for dom to load before booting react. we could alternatively
|
// 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.
|
// 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 React, {Component} from 'react';
|
||||||
import {reactCellRendererFactory} from 'ag-grid-react';
|
|
||||||
import SimpleCellRenderer from './simpleCellRenderer.jsx';
|
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
|
// for enterprise features
|
||||||
// import 'ag-grid-enterprise';
|
// import {AllModules} from "@ag-grid-enterprise/all-modules";
|
||||||
|
|
||||||
export default class MyApp extends React.Component {
|
export default class MyApp extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@@ -22,22 +23,22 @@ export default class MyApp extends React.Component {
|
|||||||
|
|
||||||
createColumnNames() {
|
createColumnNames() {
|
||||||
// creates column names by iterating the alphabet twice, eg {'aa','ab','ac',.....'zz'}
|
// creates column names by iterating the alphabet twice, eg {'aa','ab','ac',.....'zz'}
|
||||||
var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
|
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
|
||||||
this.columnNames = [];
|
this.columnNames = [];
|
||||||
alphabet.forEach( letter1 => {
|
alphabet.forEach(letter1 => {
|
||||||
alphabet.forEach( letter2 => {
|
alphabet.forEach(letter2 => {
|
||||||
this.columnNames.push(letter1 + letter2);
|
this.columnNames.push(letter1 + letter2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createRowData() {
|
createRowData() {
|
||||||
var rowData = [];
|
const rowData = [];
|
||||||
|
|
||||||
for (var i = 0; i<1000; i++) {
|
for (let i = 0; i < 1000; i++) {
|
||||||
var item = {};
|
const item = {};
|
||||||
this.columnNames.forEach( colName => {
|
this.columnNames.forEach(colName => {
|
||||||
item[colName] = '('+colName.toUpperCase()+','+i+')'
|
item[colName] = '(' + colName.toUpperCase() + ',' + i + ')'
|
||||||
});
|
});
|
||||||
rowData.push(item);
|
rowData.push(item);
|
||||||
}
|
}
|
||||||
@@ -46,9 +47,9 @@ export default class MyApp extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createColumnDefs() {
|
createColumnDefs() {
|
||||||
var columnDefs = [];
|
const columnDefs = [];
|
||||||
|
|
||||||
this.columnNames.forEach( colName => {
|
this.columnNames.forEach(colName => {
|
||||||
columnDefs.push({
|
columnDefs.push({
|
||||||
headerName: colName.toUpperCase(),
|
headerName: colName.toUpperCase(),
|
||||||
field: colName,
|
field: colName,
|
||||||
@@ -62,8 +63,8 @@ export default class MyApp extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{height: '100%'}} className="ag-fresh">
|
<div style={{height: '100%'}} className="ag-theme-fresh">
|
||||||
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} />
|
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} modules={AllModules}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
|
||||||
import {AgGridReact} from "ag-grid-react";
|
import {AgGridReact} from "@ag-grid-community/react";
|
||||||
|
|
||||||
import assign from "lodash/assign";
|
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
|
||||||
import uniq from "lodash/uniq";
|
|
||||||
|
|
||||||
class FxQuoteMatrix extends Component {
|
class FxQuoteMatrix extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -35,41 +34,47 @@ class FxQuoteMatrix extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const newRowData = nextProps.rowData;
|
if (this.gridApi) {
|
||||||
|
const newRowData = nextProps.rowData;
|
||||||
|
|
||||||
const updatedRows = [];
|
const updatedRows = [];
|
||||||
|
|
||||||
for (let i = 0; i < newRowData.length; i++) {
|
for (let i = 0; i < newRowData.length; i++) {
|
||||||
let newRow = newRowData[i];
|
let newRow = newRowData[i];
|
||||||
let currentRowNode = this.gridApi.getRowNode(newRow.symbol);
|
let currentRowNode = this.gridApi.getRowNode(newRow.symbol);
|
||||||
|
|
||||||
const {data} = currentRowNode;
|
const {data} = currentRowNode;
|
||||||
for (const def of this.state.columnDefs) {
|
for (const def of this.state.columnDefs) {
|
||||||
if (data[def.field] !== newRow[def.field]) {
|
if (data[def.field] !== newRow[def.field]) {
|
||||||
updatedRows.push(newRow);
|
updatedRows.push(newRow);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.gridApi.updateRowData({update: updatedRows});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.gridApi.updateRowData({update: updatedRows});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{height: 410, width: 800}}
|
<div style={{height: 410, width: 800}}
|
||||||
className="ag-fresh">
|
className="ag-theme-fresh">
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
// properties
|
// properties
|
||||||
columnDefs={this.state.columnDefs}
|
columnDefs={this.state.columnDefs}
|
||||||
enableSorting="false"
|
defaultColDef={{
|
||||||
enableFilter="false"
|
sortable: false,
|
||||||
|
filter: false
|
||||||
|
}}
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
getRowNodeId={this.getRowNodeId}
|
getRowNodeId={this.getRowNodeId}
|
||||||
|
|
||||||
|
modules={[ClientSideRowModelModule]}
|
||||||
|
|
||||||
// events
|
// events
|
||||||
onGridReady={this.onGridReady}>
|
onGridReady={this.onGridReady}>
|
||||||
</AgGridReact>
|
</AgGridReact>
|
||||||
@@ -81,7 +86,7 @@ class FxQuoteMatrix extends Component {
|
|||||||
export default connect(
|
export default connect(
|
||||||
(state) => {
|
(state) => {
|
||||||
return {
|
return {
|
||||||
rowData: state.fxData
|
rowData: state ? state.fxData : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)(FxQuoteMatrix);
|
)(FxQuoteMatrix);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, {Component} from "react";
|
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 map from "lodash/map";
|
||||||
import difference from "lodash/difference";
|
import difference from "lodash/difference";
|
||||||
@@ -24,21 +25,21 @@ export default class extends Component {
|
|||||||
field: 'price',
|
field: 'price',
|
||||||
headerName: 'Price',
|
headerName: 'Price',
|
||||||
valueFormatter: this.numberFormatter,
|
valueFormatter: this.numberFormatter,
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellStyle: {'text-align': 'right'}
|
cellStyle: {'text-align': 'right'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'bid',
|
field: 'bid',
|
||||||
headerName: 'Bid',
|
headerName: 'Bid',
|
||||||
valueFormatter: this.numberFormatter,
|
valueFormatter: this.numberFormatter,
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellStyle: {'text-align': 'right'}
|
cellStyle: {'text-align': 'right'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'ask',
|
field: 'ask',
|
||||||
headerName: 'Ask',
|
headerName: 'Ask',
|
||||||
valueFormatter: this.numberFormatter,
|
valueFormatter: this.numberFormatter,
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellStyle: {'text-align': 'right'}
|
cellStyle: {'text-align': 'right'}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -151,13 +152,17 @@ export default class extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{height: 410, width: 800}}
|
<div style={{height: 410, width: 800}}
|
||||||
className="ag-fresh">
|
className="ag-theme-fresh">
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
// properties
|
// properties
|
||||||
columnDefs={this.state.columnDefs}
|
columnDefs={this.state.columnDefs}
|
||||||
enableSorting="true"
|
defaultColDef={{
|
||||||
|
sortable: true
|
||||||
|
}}
|
||||||
rowSelection="single"
|
rowSelection="single"
|
||||||
|
|
||||||
|
modules={[ClientSideRowModelModule]}
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
getRowNodeId={this.getRowNodeId}
|
getRowNodeId={this.getRowNodeId}
|
||||||
|
|
||||||
@@ -168,4 +173,4 @@ export default class extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {connect} from "react-redux";
|
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 {
|
class TopMoversGrid extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -17,24 +18,24 @@ class TopMoversGrid extends Component {
|
|||||||
field: 'last',
|
field: 'last',
|
||||||
headerName: 'Last',
|
headerName: 'Last',
|
||||||
headerClass: 'align-right',
|
headerClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClass: 'align-right'
|
cellClass: 'align-right'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'net',
|
field: 'net',
|
||||||
headerName: 'Net',
|
headerName: 'Net',
|
||||||
headerClass: 'align-right',
|
headerClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClass: 'align-right'
|
cellClass: 'align-right'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'pct_net_change',
|
field: 'pct_net_change',
|
||||||
headerName: '% NC',
|
headerName: '% NC',
|
||||||
headerClass: 'align-right',
|
headerClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClass: 'align-right',
|
cellClass: 'align-right',
|
||||||
sort: 'desc',
|
sort: 'desc',
|
||||||
cellFormatter(params) {
|
valueFormatter(params) {
|
||||||
return params.value.toFixed(2)
|
return params.value.toFixed(2)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -62,17 +63,21 @@ class TopMoversGrid extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{height: 410, width: 400}}
|
<div style={{height: 410, width: 400}}
|
||||||
className="ag-fresh">
|
className="ag-theme-fresh">
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
// properties
|
// properties
|
||||||
columnDefs={this.state.columnDefs}
|
columnDefs={this.state.columnDefs}
|
||||||
rowData={this.props.rowData}
|
rowData={this.props.rowData}
|
||||||
enableSorting
|
defaultColDef={{
|
||||||
enableFilter="false"
|
sortable: true,
|
||||||
|
filter: false
|
||||||
|
}}
|
||||||
animateRows
|
animateRows
|
||||||
deltaRowDataMode
|
deltaRowDataMode
|
||||||
getRowNodeId={this.getRowNodeId}
|
getRowNodeId={this.getRowNodeId}
|
||||||
|
|
||||||
|
modules={[ClientSideRowModelModule]}
|
||||||
|
|
||||||
// events
|
// events
|
||||||
onGridReady={this.onGridReady}>
|
onGridReady={this.onGridReady}>
|
||||||
</AgGridReact>
|
</AgGridReact>
|
||||||
@@ -84,7 +89,7 @@ class TopMoversGrid extends Component {
|
|||||||
export default connect(
|
export default connect(
|
||||||
(state) => {
|
(state) => {
|
||||||
return {
|
return {
|
||||||
rowData: state.fxTopMovers
|
rowData: state ? state.fxTopMovers : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)(TopMoversGrid);
|
)(TopMoversGrid);
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ import * as PropTypes from 'prop-types';
|
|||||||
|
|
||||||
export default class HorizontalBarComponent extends Component {
|
export default class HorizontalBarComponent extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
value: this.props.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let positiveChange = {
|
let positiveChange = {
|
||||||
fill: "green"
|
fill: "green"
|
||||||
@@ -19,7 +27,7 @@ export default class HorizontalBarComponent extends Component {
|
|||||||
textAlign: "right"
|
textAlign: "right"
|
||||||
};
|
};
|
||||||
|
|
||||||
let pctNetChange = this.props.value;
|
let pctNetChange = this.state.value;
|
||||||
let pctNetChangeBar = Math.min(Math.abs(pctNetChange) * 100, 100) / 2;
|
let pctNetChangeBar = Math.min(Math.abs(pctNetChange) * 100, 100) / 2;
|
||||||
|
|
||||||
let barWidth = `${pctNetChangeBar}%`;
|
let barWidth = `${pctNetChangeBar}%`;
|
||||||
@@ -36,6 +44,13 @@ export default class HorizontalBarComponent extends Component {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh(params) {
|
||||||
|
this.setState({
|
||||||
|
value: params.value
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalBarComponent.propTypes = {
|
HorizontalBarComponent.propTypes = {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<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>
|
<style>
|
||||||
html, body {
|
html, body {
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import {render} from "react-dom";
|
|||||||
|
|
||||||
import {Provider} from "react-redux";
|
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 StoreService from './services/StoreService';
|
||||||
import TraderDashboard from "./components/TraderDashboard.jsx";
|
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-fresh.css";
|
||||||
|
|
||||||
let store = StoreService.STORE;
|
let store = StoreService.STORE;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ const FX_DELTA_HEADERS = [
|
|||||||
field: 'last',
|
field: 'last',
|
||||||
headerName: 'Last',
|
headerName: 'Last',
|
||||||
headerClass: 'align-right',
|
headerClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClass: 'align-right',
|
cellClass: 'align-right',
|
||||||
width: 100
|
width: 100
|
||||||
},
|
},
|
||||||
@@ -128,7 +128,7 @@ const FX_DELTA_HEADERS = [
|
|||||||
field: 'net',
|
field: 'net',
|
||||||
headerName: 'Net',
|
headerName: 'Net',
|
||||||
headerClass: 'align-right',
|
headerClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClass: 'align-right',
|
cellClass: 'align-right',
|
||||||
width: 90
|
width: 90
|
||||||
},
|
},
|
||||||
@@ -145,7 +145,7 @@ const FX_DELTA_HEADERS = [
|
|||||||
headerName: symbol,
|
headerName: symbol,
|
||||||
width: 67,
|
width: 67,
|
||||||
cellClass: 'align-right',
|
cellClass: 'align-right',
|
||||||
cellRenderer: 'animateShowChange',
|
cellRenderer: 'agAnimateShowChangeCellRenderer',
|
||||||
cellClassRules: {
|
cellClassRules: {
|
||||||
'fx-positive': 'x > 0.8',
|
'fx-positive': 'x > 0.8',
|
||||||
'fx-null': 'x === null',
|
'fx-null': 'x === null',
|
||||||
|
|||||||
159
src/App.jsx
@@ -1,159 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
import {Redirect, Route, Switch} from "react-router-dom";
|
|
||||||
|
|
||||||
import NavItem from "./NavItem";
|
|
||||||
|
|
||||||
import DynamicComponentsExample from "./dynamicComponentExample/DynamicComponentsExample";
|
|
||||||
import RichGridExample from "./richGridExample/RichGridExample";
|
|
||||||
import RichComponentsExample from "./richComponentExample/RichComponentsExample";
|
|
||||||
import EditorComponentsExample from "./editorComponentExample/EditorComponentsExample";
|
|
||||||
import PinnedRowComponentExample from "./pinnedRowExample/PinnedRowComponentExample";
|
|
||||||
import FullWidthComponentExample from "./fullWidthExample/FullWidthComponentExample";
|
|
||||||
import GroupedRowInnerRendererComponentExample from "./groupedRowInnerRendererExample/GroupedRowInnerRendererComponentExample";
|
|
||||||
import FilterComponentExample from "./filterComponentExample/FilterComponentExample";
|
|
||||||
import MasterDetailExample from "./masterDetailExample/MasterDetailExample";
|
|
||||||
import SimpleReduxExample from "./simpleReduxExample/SimpleReduxExample";
|
|
||||||
import FloatingFilterGridExample from "./floatingFilter/FloatingFilterGridExample";
|
|
||||||
import SimpleReduxDynamicExample from "./simpleReduxDynamicComponentExample/SimpleReduxExample";
|
|
||||||
|
|
||||||
const SideBar = () => (
|
|
||||||
<div style={{float: "left", width: 335, marginRight: 25}}>
|
|
||||||
<ul className="nav nav-pills nav-stacked">
|
|
||||||
<NavItem to='/rich-grid'>Rich Grid Example</NavItem>
|
|
||||||
<NavItem to='/dynamic'>Dynamic React Component Example</NavItem>
|
|
||||||
<NavItem to='/rich-dynamic'>Dynamic React Components - Richer Example</NavItem>
|
|
||||||
<NavItem to='/editor'>Cell Editor Component Example</NavItem>
|
|
||||||
<NavItem to='/floating-row'>Floating Row Renderer Example</NavItem>
|
|
||||||
<NavItem to='/full-width'>Full Width Renderer Example</NavItem>
|
|
||||||
<NavItem to='/group-row'>Grouped Row Inner Renderer Example</NavItem>
|
|
||||||
<NavItem to='/filter'>Filters Component Example</NavItem>
|
|
||||||
<NavItem to='/master-detail'>Master Detail Example</NavItem>
|
|
||||||
<NavItem to='/floating-filter'>Floating Filters</NavItem>
|
|
||||||
<NavItem to='/simple-redux'>Simple Redux Example</NavItem>
|
|
||||||
<NavItem to='/simple-redux-dynamic'>Simple Redux Dynamic Component Example</NavItem>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
class App extends Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div style={{display: "inline-block", width: "100%"}}>
|
|
||||||
<SideBar/>
|
|
||||||
<div style={{float: "left"}}>
|
|
||||||
<Switch>
|
|
||||||
<Redirect from="/" exact to="/rich-grid"/>
|
|
||||||
<Route exact path='/rich-grid' component={RichGridExample}/>
|
|
||||||
<Route exact path='/dynamic' component={DynamicComponentsExample}/>
|
|
||||||
<Route exact path='/rich-dynamic' component={RichComponentsExample}/>
|
|
||||||
<Route exact path='/editor' component={EditorComponentsExample}/>
|
|
||||||
<Route exact path='/floating-row' component={PinnedRowComponentExample}/>
|
|
||||||
<Route exact path='/full-width' component={FullWidthComponentExample}/>
|
|
||||||
<Route exact path='/group-row' component={GroupedRowInnerRendererComponentExample}/>
|
|
||||||
<Route exact path='/filter' component={FilterComponentExample}/>
|
|
||||||
<Route exact path='/master-detail' component={MasterDetailExample}/>
|
|
||||||
<Route exact path='/floating-filter' component={FloatingFilterGridExample}/>
|
|
||||||
<Route exact path='/simple-redux' component={SimpleReduxExample}/>
|
|
||||||
<Route exact path='/simple-redux-dynamic' component={SimpleReduxDynamicExample}/>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App
|
|
||||||
|
|
||||||
/*
|
|
||||||
class App extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
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 === 'pinned-row' ? 'active' : null} onClick={() => this.setExample("pinned-row")}><a href="#">Pinned Row Renderer Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'full-width' ? 'active' : null} onClick={() => this.setExample("full-width")}><a href="#">Full Width Renderer Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'group-row' ? 'active' : null} onClick={() => this.setExample("group-row")}><a href="#">Grouped Row Inner Renderer Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'filter' ? 'active' : null} onClick={() => this.setExample("filter")}><a href="#">Filters Component Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'floating-filter' ? 'active' : null} onClick={() => this.setExample("floating-filter")}><a href="#">Floating Filters</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'master-detail' ? 'active' : null} onClick={() => this.setExample("master-detail")}><a href="#">Master Detail Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'simple-redux' ? 'active' : null} onClick={() => this.setExample("simple-redux")}><a href="#">Simple Redux Example</a></li>
|
|
||||||
<li role="presentation" className={this.state.example === 'simple-redux-dynamic' ? 'active' : null} onClick={() => this.setExample("simple-redux-dynamic")}><a href="#">Simple Redux Dynamic Component Example</a></li>
|
|
||||||
</ul>)
|
|
||||||
}
|
|
||||||
|
|
||||||
let example = null;
|
|
||||||
switch (this.state.example) {
|
|
||||||
case 'dynamic':
|
|
||||||
example = <DynamicComponentsExample/>;
|
|
||||||
break;
|
|
||||||
case 'rich-dynamic':
|
|
||||||
example = <RichComponentsExample/>;
|
|
||||||
break;
|
|
||||||
case 'editor':
|
|
||||||
example = <EditorComponentsExample/>;
|
|
||||||
break;
|
|
||||||
case 'pinned-row':
|
|
||||||
example = <PinnedRowComponentExample/>;
|
|
||||||
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 = <FloatingFilterGridExample/>;
|
|
||||||
break;
|
|
||||||
case 'simple-redux-dynamic':
|
|
||||||
example = <SimpleReduxDynamicExample/>;
|
|
||||||
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, lineHeight: 0.5}} onClick={this.invokeParentMethod} className="btn btn-info">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,31 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
|
|
||||||
export default class CurrencyRenderer extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
value: props.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
formatValueToCurrency(currency, value) {
|
|
||||||
return `${currency}${value}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
refresh(params) {
|
|
||||||
if(params.value !== this.state.value) {
|
|
||||||
this.setState({
|
|
||||||
value: params.value.toFixed(2)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<span>{this.formatValueToCurrency('EUR', this.state.value)}</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,153 +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: DynamicComponentsExample.createRowData(),
|
|
||||||
|
|
||||||
columnDefs: DynamicComponentsExample.createColumnDefs()
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onGridReady = this.onGridReady.bind(this);
|
|
||||||
this.refreshEvenRowsCurrencyData = this.refreshEvenRowsCurrencyData.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGridReady(params) {
|
|
||||||
this.gridApi = params.api;
|
|
||||||
this.columnApi = params.columnApi;
|
|
||||||
|
|
||||||
this.gridApi.sizeColumnsToFit();
|
|
||||||
}
|
|
||||||
|
|
||||||
methodFromParent(cell) {
|
|
||||||
alert(`Parent Component Method from ${cell}!`);
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshEvenRowsCurrencyData() {
|
|
||||||
this.gridApi.forEachNode(rowNode => {
|
|
||||||
if (rowNode.data.value % 2 === 0) {
|
|
||||||
rowNode.setDataValue('currency', rowNode.data.value + Number(Math.random().toFixed(2)))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.gridApi.refreshCells({
|
|
||||||
columns: ['currency']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
static createColumnDefs() {
|
|
||||||
return [
|
|
||||||
{headerName: "Row", field: "row", width: 100},
|
|
||||||
{
|
|
||||||
headerName: "Square",
|
|
||||||
field: "value",
|
|
||||||
cellRendererFramework: SquareRenderer,
|
|
||||||
editable: true,
|
|
||||||
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: "currency",
|
|
||||||
width: 135
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Child/Parent",
|
|
||||||
field: "value",
|
|
||||||
cellRendererFramework: ChildMessageRenderer,
|
|
||||||
colId: "params",
|
|
||||||
width: 120
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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: 900}}
|
|
||||||
className="ag-fresh">
|
|
||||||
<h1>Dynamic React Component Example</h1>
|
|
||||||
<button onClick={this.refreshEvenRowsCurrencyData} style={{marginBottom: 10}} className="btn btn-primary">Refresh Even Row Currency Data</button>
|
|
||||||
<AgGridReact
|
|
||||||
// properties
|
|
||||||
columnDefs={this.state.columnDefs}
|
|
||||||
rowData={this.state.rowData}
|
|
||||||
gridOptions={this.state.gridOptions}
|
|
||||||
|
|
||||||
// events
|
|
||||||
onGridReady={this.onGridReady}>
|
|
||||||
</AgGridReact>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-sm-12"><h1>Dynamic React Component Example</h1></div>
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<h5>This example demonstrates Dynamic React Components with ag-Grid, Parent/Child Communication (cell component to parent grid component), as well as
|
|
||||||
dynamic data updates of the <code>Currency</code> column.</h5>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Square, Cube, Row Params, Currency and Child/Parent</span>: React Components within the Grid</p>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Currency (Pipe)</span>: An React Component mimicking a Currency Pipe, dynamically updated with the button above.</p>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Child/Parent</span>: Demonstrates the Child Cell Component communicating with the Parent Grid Component.</p>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Refresh Even Row Currency Data</span>: Dynamically Updates Event Rows Currency Value. Only the Currency column will be re-rendered.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-body">
|
|
||||||
<h4 className="card-title">React Functionality</h4>
|
|
||||||
<p className="card-text">Utilise React Components within ag-Grid</p>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-rendering-components/?framework=react" className="btn btn-primary">React Renderers</a>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-data-update/" className="btn btn-primary">Updating Data</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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,132 +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: EditorComponentsExample.createRowData(),
|
|
||||||
columnDefs: EditorComponentsExample.createColumnDefs()
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onGridReady = this.onGridReady.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGridReady(params) {
|
|
||||||
this.gridApi = params.api;
|
|
||||||
this.columnApi = params.columnApi;
|
|
||||||
|
|
||||||
this.gridApi.sizeColumnsToFit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static createColumnDefs() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
headerName: "Name",
|
|
||||||
field: "name",
|
|
||||||
width: 300,
|
|
||||||
editable: true,
|
|
||||||
cellEditor: 'richSelect',
|
|
||||||
cellEditorParams: {
|
|
||||||
values: [
|
|
||||||
"Bob",
|
|
||||||
"Harry",
|
|
||||||
"Sally",
|
|
||||||
"Mary",
|
|
||||||
"John",
|
|
||||||
"Jack",
|
|
||||||
"Sue",
|
|
||||||
"Sean",
|
|
||||||
"Niall",
|
|
||||||
"Albert",
|
|
||||||
"Fred",
|
|
||||||
"Jenny",
|
|
||||||
"Larry"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Mood",
|
|
||||||
field: "mood",
|
|
||||||
cellRendererFramework: MoodRenderer,
|
|
||||||
cellEditorFramework: MoodEditor,
|
|
||||||
editable: true,
|
|
||||||
width: 250
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Numeric",
|
|
||||||
field: "number",
|
|
||||||
cellEditorFramework: NumericEditor,
|
|
||||||
editable: true,
|
|
||||||
width: 250
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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: 370, width: 900}}
|
|
||||||
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 className="row">
|
|
||||||
<div className="col-sm-12"><h1>Cell Editor Component Example</h1></div>
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<h5>This example demonstrates React Editor Components within ag-Grid, as well as an example using the built in Rich Select editor.</h5>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Name</span>: Utilises the built in <code>RichSelect</code> editor</p>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Mood</span>: A Custom React Editor demonstrating popup functionality, with full keyboard control.</p>
|
|
||||||
<p><span style={{fontWeight: "bold"}}>Numeric</span>: A Custom React Editor demonstrating pre & post validation. Only numeric characters are allowed,
|
|
||||||
and numbers greater than 1000000 will be rejected.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-body">
|
|
||||||
<h4 className="card-title">React Functionality</h4>
|
|
||||||
<p className="card-text">Utilise React Components within ag-Grid</p>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editing/?framework=react" className="btn btn-primary">Cell Editing</a>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react" className="btn btn-primary">Editor Components</a>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
|
|
||||||
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react#reactCellEditing" className="btn btn-primary">React Editor Components</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,120 +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.refs.container.addEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.refs.container.removeEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAndToggleMoodIfLeftRight = (event) => {
|
|
||||||
if ([37, 39].indexOf(event.keyCode) > -1) { // left and right
|
|
||||||
this.toggleMood();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
};
|
|
||||||
|
|
||||||
let unselected = {
|
|
||||||
paddingLeft: 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.happy ? selected : unselected;
|
|
||||||
let sadStyle = !this.state.happy ? selected : unselected;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref="container"
|
|
||||||
style={mood}
|
|
||||||
tabIndex={1} // important - without this the keypresses wont be caught
|
|
||||||
>
|
|
||||||
<img src="images/smiley.png" onClick={this.onHappyClick} style={happyStyle}/>
|
|
||||||
<img src="images/smiley-sad.png" onClick={this.onSadClick} style={sadStyle}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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,99 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
|
|
||||||
export default class MoodEditor extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.cancelBeforeStart = this.props.charPress && ('1234567890'.indexOf(this.props.charPress) < 0);
|
|
||||||
|
|
||||||
let value = this.props.value;
|
|
||||||
if (!this.cancelBeforeStart && this.props.charPress) {
|
|
||||||
value = value + this.props.charPress;
|
|
||||||
}
|
|
||||||
this.state = {
|
|
||||||
value
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onKeyDown = this.onKeyDown.bind(this);
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.refs.input.addEventListener('keydown', this.onKeyDown);
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.refs.input.removeEventListener('keydown', this.onKeyDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.refs.input.focus();
|
|
||||||
this.refs.input.setSelectionRange(this.state.value.length, this.state.value.length);
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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.isLeftOrRight(event)) {
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isKeyPressedNumeric(event)) {
|
|
||||||
if (event.preventDefault) event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isLeftOrRight(event) {
|
|
||||||
return [37, 39].indexOf(event.keyCode) > -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(event) {
|
|
||||||
this.setState({value: event.target.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
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}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
style={{width: "100%"}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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: FilterComponentExample.createRowData(),
|
|
||||||
columnDefs: FilterComponentExample.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!");
|
|
||||||
}
|
|
||||||
|
|
||||||
static createColumnDefs() {
|
|
||||||
return [
|
|
||||||
{headerName: "Row", field: "row", width: 400},
|
|
||||||
{
|
|
||||||
headerName: "Filter Component",
|
|
||||||
field: "name",
|
|
||||||
filterFramework: PartialMatchFilter,
|
|
||||||
width: 400,
|
|
||||||
menuTabs:['filterMenuTab']
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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: 900}}
|
|
||||||
className="ag-fresh">
|
|
||||||
<h1>Filter Component Example</h1>
|
|
||||||
<button style={{marginBottom: 10}} onClick={this.onClicked} className="btn btn-primary">Filter Instance Method</button>
|
|
||||||
<AgGridReact
|
|
||||||
// properties
|
|
||||||
columnDefs={this.state.columnDefs}
|
|
||||||
rowData={this.state.rowData}
|
|
||||||
|
|
||||||
enableFilter
|
|
||||||
|
|
||||||
// events
|
|
||||||
onGridReady={this.onGridReady}>
|
|
||||||
</AgGridReact>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,80 +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() {
|
|
||||||
let style = {
|
|
||||||
border: "2px solid #22ff22",
|
|
||||||
borderRadius: "5px",
|
|
||||||
backgroundColor: "#bbffbb",
|
|
||||||
width: "200px",
|
|
||||||
height: "50px"
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={style}>Filter: <input style={{height: "20px"}} ref="input" value={this.state.text}
|
|
||||||
onChange={this.onChange} className="form-control"/></div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
import {AgGridReact} from "ag-grid-react";
|
|
||||||
import FloatingFilter from "./floatingFilter";
|
|
||||||
import overrideStyle from "./floatingFilter.css";
|
|
||||||
|
|
||||||
export default class FloatingFilterGridExample extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
columnDefs: this.createColumnDefs(),
|
|
||||||
rowData: this.createRowData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onGridReady(params) {
|
|
||||||
this.gridApi = params.api;
|
|
||||||
this.columnApi = params.columnApi;
|
|
||||||
|
|
||||||
this.gridApi.sizeColumnsToFit();
|
|
||||||
}
|
|
||||||
|
|
||||||
createColumnDefs() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
headerName: "Make",
|
|
||||||
field: "make",
|
|
||||||
floatingFilterComponentFramework: FloatingFilter,
|
|
||||||
filter: 'set'
|
|
||||||
},
|
|
||||||
{headerName: "Model", field: "model"},
|
|
||||||
{headerName: "Price", field: "price"}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
createRowData() {
|
|
||||||
return [
|
|
||||||
{make: "Toyota", model: "Celica", price: 35000},
|
|
||||||
{make: "Ford", model: "Mondeo", price: 32000},
|
|
||||||
{make: "Porsche", model: "Boxter", price: 72000}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let divStyle = {
|
|
||||||
height: 400,
|
|
||||||
width: 900
|
|
||||||
};
|
|
||||||
|
|
||||||
// combine the styles
|
|
||||||
const style = Object.assign({}, divStyle, overrideStyle);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={style} className="ag-fresh">
|
|
||||||
<h1>Floating Filter Example</h1>
|
|
||||||
<AgGridReact
|
|
||||||
// properties
|
|
||||||
columnDefs={this.state.columnDefs}
|
|
||||||
rowData={this.state.rowData}
|
|
||||||
|
|
||||||
floatingFilter={true}
|
|
||||||
|
|
||||||
// events
|
|
||||||
onGridReady={this.onGridReady}>
|
|
||||||
</AgGridReact>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
.ag-floating-filter-button button {
|
|
||||||
margin: 0
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
|
|
||||||
export default class FloatingFilter extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
parentModel: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// when does this get called? how to test this?
|
|
||||||
onParentModelChanged(parentModel) {
|
|
||||||
this.setState({
|
|
||||||
parentModel: parentModel
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(item) {
|
|
||||||
this.props.onFloatingFilterChanged({
|
|
||||||
model: this.state.parentModel.filter(it => it !== item)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (!this.state.parentModel) return null;
|
|
||||||
|
|
||||||
// as the backing filter is a set filter what we're doing here is rendering the list in the set
|
|
||||||
// and when the [x] removing the selected item, thereby effectively hiding it
|
|
||||||
let options = this.state.parentModel.map((item, i) => {
|
|
||||||
let removeMeListener = () => {
|
|
||||||
this.remove(item)
|
|
||||||
};
|
|
||||||
let removeMeElement = <a onClick={removeMeListener}>[x]</a>;
|
|
||||||
return <span key={i}>{item}{removeMeElement}</span>;
|
|
||||||
});
|
|
||||||
|
|
||||||
return <div>{options}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
import React, {Component} from "react";
|
|
||||||
|
|
||||||
import {AgGridReact} from "ag-grid-react";
|
|
||||||
import NameAndAgeRenderer from "./NameAndAgeRenderer";
|
|
||||||
|
|
||||||
export default class FullWidthComponentExample extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
gridOptions: {},
|
|
||||||
|
|
||||||
rowData: FullWidthComponentExample.createRowData(),
|
|
||||||
columnDefs: FullWidthComponentExample.createColumnDefs()
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onGridReady = this.onGridReady.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onGridReady(params) {
|
|
||||||
this.gridApi = params.api;
|
|
||||||
this.columnApi = params.columnApi;
|
|
||||||
|
|
||||||
this.gridApi.sizeColumnsToFit();
|
|
||||||
}
|
|
||||||
|
|
||||||
isFullWidthCell(rowNode) {
|
|
||||||
return (rowNode.id === "0") || (parseInt(rowNode.id) % 2 === 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static createColumnDefs() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
headerName: "Name",
|
|
||||||
field: "name",
|
|
||||||
width: 400
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Age",
|
|
||||||
field: "age",
|
|
||||||
width: 399
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static createRowData() {
|
|
||||||
return [
|
|
||||||
{name: "Bob", age: 10},
|
|
||||||
{name: "Harry", age: 3},
|
|
||||||
{name: "Sally", age: 20},
|
|
||||||
{name: "Mary", age: 5},
|
|
||||||
{name: "John", age: 15},
|
|
||||||
{name: "Bob", age: 10},
|
|
||||||
{name: "Harry", age: 3},
|
|
||||||
{name: "Sally", age: 20},
|
|
||||||
{name: "Mary", age: 5},
|
|
||||||
{name: "John", age: 15},
|
|
||||||
{name: "Jack", age: 25},
|
|
||||||
{name: "Sue", age: 43},
|
|
||||||
{name: "Sean", age: 44},
|
|
||||||
{name: "Niall", age: 2},
|
|
||||||
{name: "Alberto", age: 32},
|
|
||||||
{name: "Fred", age: 53},
|
|
||||||
{name: "Jenny", age: 34},
|
|
||||||
{name: "Larry", age: 13},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div style={{height: 400, width: 900}}
|
|
||||||
className="ag-fresh">
|
|
||||||
<h1>Full Width Renderer Example</h1>
|
|
||||||
<AgGridReact
|
|
||||||
// properties
|
|
||||||
columnDefs={this.state.columnDefs}
|
|
||||||
rowData={this.state.rowData}
|
|
||||||
|
|
||||||
isFullWidthCell={this.isFullWidthCell}
|
|
||||||
fullWidthCellRendererFramework={NameAndAgeRenderer}
|
|
||||||
|
|
||||||
// events
|
|
||||||
onGridReady={this.onGridReady}>
|
|
||||||
</AgGridReact>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||