Compare commits

...

171 Commits

Author SHA1 Message Date
Sean Landsman
d19c461847 Merge branch 'b23.0.0' 2020-03-17 14:29:28 +00:00
Sean Landsman
2d5fea4790 Release 23.0.0 2020-03-11 08:16:58 +00:00
Adrian Lowdon
c680bffd5a AG-3390 - fixed icon 2020-02-18 15:48:10 +00:00
Guilherme Lopes Portela
917277bfe1 updated boostrap 2020-02-03 22:38:26 +00:00
Sean Landsman
d2cb2149cc AG-3790 Vue component not found if not within immediate parent 2020-01-29 10:28:03 +00:00
Sean Landsman
0954bec3ee Utility script 2020-01-14 09:44:17 +00:00
Bernie Sumption
89d76cd1ac Moved from fresh theme to balham 2019-12-11 15:53:40 +00:00
Sean Landsman
f2b515af7f Merge branch 'b22.1.0' 2019-12-06 10:45:32 +00:00
Sean Landsman
5561283927 Merge from latest (22.0.0) 2019-12-03 16:02:04 +00:00
Sean Landsman
86c353eaa9 Release 22.1.0 2019-12-02 14:30:27 +00:00
Sean Landsman
52cf4512a9 AG-3600 React - memoized functions don't render 2019-11-21 14:55:31 +00:00
Sean Landsman
611d668981 Merge branch 'b22.0.0' into latest 2019-11-11 15:02:22 +00:00
Sean Landsman
67fdecbe51 Release 22.0.0 2019-11-11 14:48:41 +00:00
Sean Landsman
5ad3592fed AG-1329 Update examples 2019-11-11 11:22:13 +00:00
Sean Landsman
ff7c46e553 AG-1329 Add licenses etc to new packages 2019-11-08 10:54:47 +00:00
Sean Landsman
1c1e1bf555 AG-1329 Rename packages to new scopes (@ag-grid-community & @ag-grid-enterprise) 2019-11-05 09:18:50 +00:00
Sean Landsman
6ad4493357 AG-1329 Rename packages to new scopes (@ag-grid-community & @ag-grid-enterprise) 2019-11-04 20:25:39 +00:00
Sean Landsman
1cf70a551e Merge branch 'latest' into b22.0.0 2019-10-25 12:41:54 +01:00
Sean Landsman
fcc2bfffcd Merge branch 'latest' into b22.0.0 2019-10-25 11:11:08 +01:00
Sean Landsman
3e8b1b7979 Merge branch 'latest' into b22.0.0 2019-10-24 09:35:46 +01:00
Sean Landsman
61420e0d67 AG-1329 Move ag-grid-react and ag-grid-vue to modules 2019-10-23 20:25:40 +01:00
Sean Landsman
bd63d49c52 Release 22.0.0 2019-10-23 11:23:35 +01:00
Sean Landsman
36eb9c8a18 AG-1329 Fix source map issue, change versions, clean modules 2019-10-22 16:58:54 +01:00
Sean Landsman
b4c3ebc248 AG-1329 Update framework examples and tests 2019-10-18 20:46:09 +01:00
Sean Landsman
51621200da AG-1329 Modularisation work - update examples 2019-10-18 18:40:14 +01:00
Sean Landsman
46c26f074e AG-1329 Add modularisation mechanism 2019-10-09 18:41:11 +01:00
Sean Landsman
894d971f0e AG-3316 agGridReact needs to be updated to use the updated react lifecycle hooks 2019-09-30 15:00:08 +01:00
Sean Landsman
0584234be7 AG-3316 agGridReact needs to be updated to use the updated react lifecycle hooks 2019-09-25 12:22:09 +01:00
Sean Landsman
b9b2b03a6b AG-2914 DOCS - Add docs around react hooks with editors. 2019-09-23 14:29:21 +01:00
Sean Landsman
5a26863aff AG-3316 agGridReact needs to be updated to use the updated react lifecycle hooks 2019-09-16 15:45:07 +01:00
Sean Landsman
3223b82616 AG-3294 Update and improve build process 2019-09-10 12:32:05 +01:00
Sean Landsman
66580db71c Merge branch 'b21.2.0' 2019-08-30 13:18:33 +01:00
Sean Landsman
aafdfc1a62 Update dist files 2019-08-29 14:49:26 +01:00
Sean Landsman
3a9e138d28 Merge branch 'b21.1.0' 2019-07-18 11:56:55 +01:00
Sean Landsman
6eb9fdf572 Release 21.1.0 dist files added and license key updated 2019-07-15 08:43:16 +01:00
Sean Landsman
70f747e9f3 Update example versions 2019-06-04 15:39:31 +01:00
Sean Landsman
29152268bc Update example versions 2019-06-04 15:35:54 +01:00
Sean Landsman
25962ee140 Merge branch 'b21.0.0' 2019-06-04 13:50:31 +01:00
Sean Landsman
b26dfb5b82 Release 21.0.0 dist files added and license key updated 2019-05-31 08:14:14 +01:00
Sean Landsman
cda61736cf Framework sweep (react) 2019-05-18 15:47:50 +01:00
Sean Landsman
1d59920479 Merge branch 'b20.2.0' 2019-03-22 07:55:21 +00:00
Sean Landsman
6d3b5d8bd7 Release 20.2.0 dist files added and license key updated 2019-03-20 13:55:44 +00:00
Sean Landsman
e55950227f AG-2750 Pre-release framework sweep 2019-03-19 16:30:35 +00:00
Sean Landsman
940cc314aa AG-2750 Pre-release framework sweep 2019-03-19 12:15:40 +00:00
Sean Landsman
6e31d0f067 Move react-router-dom to 5 2019-03-19 09:27:10 +00:00
Sean Landsman
5e4a94d865 AG-2750 Pre-release framework sweep 2019-03-19 08:17:15 +00:00
Sean Landsman
efa5167c54 Minor updates to deps 2019-03-18 15:08:58 +00:00
Sean Landsman
a49a05f3ed Upgrade version 2019-03-18 10:54:31 +00:00
Sean Landsman
6b06b9fa01 AG-2741 Functional components don't work with reactNext 2019-03-14 12:01:33 +00:00
Sean Landsman
eecd2a6bb2 AG-1520 React wrapper causes styling issues for components 2019-03-06 14:13:10 +00:00
Sean Landsman
ec4f7dea27 Test CI Breaks on test failure 2019-03-06 09:36:31 +00:00
Sean Landsman
3d7774e7c7 AG-2656 Allow equality checking for rowData to be configurable (ie use equality checking, deep checking and so on) 2019-03-05 14:57:53 +00:00
Sean Landsman
92ad56ed49 AG-2656 Allow equality checking for rowData to be configurable (ie use equality checking, deep checking and so on) 2019-02-27 15:26:04 +00:00
Sean Landsman
16f820c4f7 Merge branch 'b20.1.0' into master 2019-02-22 15:05:14 +00:00
Sean Landsman
839457ceda Release 20.1.0 dist files added and license key updated 2019-02-20 17:36:11 +00:00
Sean Landsman
7ff41a6966 Update fw examples 2019-02-20 15:35:12 +00:00
Sean Landsman
74ccfa6b26 AG-2653 Put React Hook example together, update docs 2019-02-12 14:45:24 +00:00
Sean Landsman
e07c66c95d AG-2264 Configuring AggregationPanel in status bar does not work if any other status panel is enabled 2019-02-08 11:00:27 +00:00
Sean Landsman
cb438ce67b Update versions 2019-01-11 11:06:50 +00:00
Sean Landsman
cb6dbfb186 Merge b20.0.0 to Master 2019-01-11 10:47:17 +00:00
Sean Landsman
f81d48b3d4 AG-2490 Regression Testing - Header component example isn't working 2019-01-09 16:58:33 +00:00
Guilherme Lopes
06fa3f01fd AG-2235 - Updated font-awesome to 5.6.3 2019-01-09 15:11:59 +00:00
Sean Landsman
d15bb746cd Release 20.0.0 dist files added and license key updated 2019-01-08 17:05:16 +00:00
Sean Landsman
3f0fe9f899 AG-644 Refactor of sorting, filtering and resizing properties 2019-01-08 16:46:07 +00:00
Sean Landsman
a3a1d74b88 Framework sweep pre-release testing 2019-01-03 12:36:17 +00:00
Sean Landsman
2b49fb1b01 AG-2114 React Components are rendered to the root of the DOM tree
AG-2417 Issue with React 6: withRef is removed. To access the wrapped instance, use a ref on the connected component
AG-2439 Add support for react-redux v6

h/t @hrgui - thanks!
2018-12-17 13:18:28 +00:00
Sean Landsman
c338f851e0 Merge branch 'master' into latest 2018-11-09 16:22:29 +00:00
Sean Landsman
58df719d45 Merge branch 'b19.1.2' 2018-11-09 15:31:00 +00:00
Sean Landsman
2b6e3e8f41 Release 19.1.2 dist files added, package.json updated, license key updated 2018-11-09 08:32:07 +00:00
Sean Landsman
f470a4c33d Merge 19.1.1 2018-10-31 16:22:47 +00:00
rmc-software
b51caf4746 Merge branch 'b19.0.0' into Master 2018-10-31 15:42:56 +00:00
rmc-software
30746397ef Updated npm and bower versions for b19.1.1 2018-10-31 13:10:02 +00:00
Sean Landsman
4998a51817 AG-2178 Add docs and example on how to use Context API with React 2018-10-16 17:42:29 +01:00
Sean Landsman
518a95ee89 AG-2177 React Example - allow force refresh (routing breaks) 2018-10-16 16:07:35 +01:00
Sean Landsman
3debbabe28 Allow more flexibility with prop-types, fix trader example 2018-10-16 15:50:21 +01:00
Guilherme Lopes
550f6c4077 updated dependencies and webpack config 2018-10-16 12:09:53 +01:00
Robert Clarke
99bc479b60 Release 19.0.0 dist files created 2018-09-05 13:11:46 +01:00
Sean Landsman
f5c1a4ba17 Update fw examples 2018-09-04 17:07:32 +01:00
Sean Landsman
168a127e51 AG-2018 Rename ag-Grid to ag-Grid-Community 2018-08-21 16:07:22 +01:00
Sean Landsman
f9b1f8527a retiring deprecated themes 2018-08-14 10:23:54 +01:00
MrSafferty
eee938e0e7 AG-1922 Framework Sweep 2018-07-18 16:03:44 +01:00
MrSafferty
449a88e832 AG-1905 Future proof ag-grid-react by removing dependency on unstable_renderSubtreeIntoContainer 2018-07-16 14:49:45 +01:00
Alberto
60181add9a Merge branch 'master' into latest
Merge branch 'master' into latest

# Conflicts:
#	package-lock.json
#	packages/ag-grid-angular/package-lock.json
#	packages/ag-grid-aurelia/package-lock.json
#	packages/ag-grid-docs/package.json
#	packages/ag-grid-enterprise/package.json
#	packages/ag-grid-react/package-lock.json
#	packages/ag-grid-vue/package-lock.json
2018-07-05 11:14:57 +01:00
Alberto
847005c758 Merge branch 'b18.1.0'
# Conflicts:
#	package.json

Merge branch 'b18.1.0'

Merge branch 'b18.1.0'

# Conflicts:
#	package-lock.json
#	package.json
#	vue.config.js
2018-07-05 11:06:51 +01:00
Alberto
ca64dae64c Release 18.1.0 dist files created 2018-07-03 11:21:25 +01:00
MrSafferty
3591b78e4b Set example repos to private 2018-07-02 11:12:58 +01:00
MrSafferty
2fedd32efd Test, Fix and Clean React Examples 2018-06-29 11:11:35 +01:00
MrSafferty
849472a031 Test, Fix and Clean React Examples 2018-06-29 10:58:22 +01:00
Minh Nguyen
a2743f9076 AG-1868 Remove dependency on react-dom-factories in ag-grid-react 2018-06-27 16:01:27 +01:00
MrSafferty
d9724f7ab5 Remove an ignore package-lock.json files 2018-06-20 17:27:35 +01:00
MrSafferty
c0443ba6ef Remove an ignore package-lock.json files 2018-06-20 17:23:06 +01:00
MrSafferty
88752be90b Further monorepo work 2018-06-14 15:42:39 +01:00
MrSafferty
2080ebb054 Bring changes from master over 2018-06-13 16:57:40 +01:00
MrSafferty
172c2a05b0 Add Vue and Aurelia Examples 2018-06-13 12:15:03 +01:00
Alberto
badb5ea485 Merge remote-tracking branch 'origin/b18.0.0'
Merge remote-tracking branch 'origin/b18.0.1'
2018-06-12 16:34:06 +01:00
Alberto
c3af000642 Release 18.0.0 setting new license key 2018-06-11 11:48:53 +01:00
Alberto
7b6b609cdf Release 18.0.0 dist files created 2018-06-11 11:29:34 +01:00
Alberto
5ffb682014 Merge remote-tracking branch 'origin/master' into latest 2018-04-17 10:09:22 +02:00
Alberto
de18262157 Merge remote-tracking branch 'origin/b17.1.0' 2018-04-17 10:05:12 +02:00
Alberto
1f6c1e41a1 Release 17.1.0 dist files created 2018-04-12 15:50:19 +01:00
Alberto
ba3762bbd3 Release 17.1.0 dist files created 2018-04-12 15:48:39 +01:00
Alberto
455f982d6c Merge remote-tracking branch 'origin/master' into latest
Merge remote-tracking branch 'origin/master' into latest

# Conflicts:
#	src/index.php
2018-03-08 12:02:45 +01:00
Alberto
0c927ae3c5 Merge remote-tracking branch 'origin/b17.0.0' 2018-03-08 11:54:52 +01:00
Alberto
2bd8d4c987 Release 17.0.0 dist files created 2018-03-05 12:59:50 +01:00
Alberto
318f78de84 Release 17.0.0 dist files created 2018-03-05 12:57:11 +01:00
Alberto
9ca52a727d Merge branch 'master' into latest 2018-01-29 11:08:55 +00:00
Alberto
56ccdd028c Merge branch 'b16.0.0' 2018-01-29 10:35:22 +00:00
Alberto
a5ccb6d622 Release 16.0.0 dist files created 2018-01-24 11:56:55 +00:00
seanlandsman
25e1f1c184 Merge pull request #34 from ag-grid/latest
AG-1294 Sweep framework examples & update versions Sprint IV
2017-12-18 11:02:15 +00:00
Alberto
8dd0f96b32 Merge branch 'master' into latest
# Conflicts:
#	angular-cli/package.json
#	ngtools_webpack/package.json
#	systemjs_aot/package.json
#	webpack/package.json
#	webpack2/package.json

Merge branch 'master' into latest

Merge branch 'master' into latest

# Conflicts:
#	package.json
2017-12-18 11:15:57 +01:00
Alberto
cf0796eb84 Merge branch 'b15.0.0' 2017-12-18 10:55:49 +01:00
Sean Landsman
a64626e67e AG-1294 Sweep framework examples & update versions Sprint IV 2017-12-15 14:29:20 +00:00
Alberto
95445e558c Release 15.0.0 dist files created 2017-12-11 21:42:59 +00:00
Alberto
79a6206026 Release 15.0.0 creating branch 2017-12-11 21:29:22 +00:00
Sean Landsman
f8ac0e5c98 Pre 15x smoke test - minor tweaks 2017-12-08 12:34:24 +00:00
Alberto
06d9e88e88 Merge master into latest post 14.2.0 2017-11-16 16:26:14 +00:00
Alberto
f860a740f3 Merge branch 'b14.2.0' 2017-11-16 16:02:35 +00:00
Sean Landsman
90ec337474 Release 14.2.0 dist/lib files created 2017-11-15 11:15:38 +00:00
Sean Landsman
05d4341dfc Release 14.2.0 creating branch 2017-11-15 10:53:49 +00:00
Sean Landsman
df77361fd4 AG-1075 Remove legacy master/detail from FW examples 2017-11-13 09:55:06 +00:00
Sean Landsman
983b5974cf AG-1053 Tidy react examples, make more idiomatic 2017-11-08 14:45:28 +00:00
Sean Landsman
b030235bbc AG-530 Implement React declarative offering 2017-11-07 16:32:03 +00:00
Sean Landsman
351d93b8fb AG-530 Implement React declarative offering 2017-11-07 16:22:19 +00:00
Alberto
43af1237bd Merge branch 'master' into latest 2017-11-03 11:23:13 +00:00
Alberto
fc76e85d77 Release 14.0.0 2017-10-31 17:03:55 +00:00
Sean Landsman
6979c51eaf v14 fixes 2017-10-31 12:07:38 +00:00
Sean Landsman
f035ee7a9d v14 changes 2017-10-31 10:16:42 +00:00
Sean Landsman
a982e0f2a7 Revert versions 2017-10-30 15:18:53 +00:00
Sean Landsman
cbb4a31be6 Merge branch 'latest' of /Users/seanlandsman/IdeaProjects/ag/ag-grid/react/ag-grid-react-example with conflicts. 2017-10-05 13:02:49 +01:00
Alberto
d2b92b4c9a Release 13.3.0 2017-10-02 14:55:11 +02:00
Sean Landsman
c8267730bf Update code to match latest changes 2017-09-28 13:56:46 +01:00
Alberto
3992e3e928 v 13.2.0 2017-09-19 10:17:51 +01:00
Alberto
8409183d6b v 13.2.0 2017-09-19 09:00:11 +01:00
Sean Landsman
7075f57d88 Tidy examples 2017-09-18 16:03:27 +01:00
Sean Landsman
ad6bc068b2 Improve react examples 2017-09-15 16:56:08 +01:00
seanlandsman
c4310c2768 Merge pull request #32 from unformatt/patch-1
Fixes typo in README
2017-09-13 14:35:08 +01:00
Alberto
2228a8d0c9 Merge branch 'master' into latest 2017-09-08 09:40:53 +01:00
Matt
966fa0fe69 Update README.md 2017-09-07 18:37:15 -04:00
Sean Landsman
9528d5a5bc Move per col icons to grid based 2017-09-04 10:39:17 +01:00
Alberto
3b5eaac21a Merge branch 'latest' into 13.1.0
# Conflicts:
#	aot/dist/agGridColumn.ngfactory.ts
#	aot/dist/agGridColumn.ngsummary.json
#	aot/dist/agGridNg2.ngfactory.ts
#	aot/dist/agGridNg2.ngsummary.json
#	aot/dist/aggrid.module.ngfactory.ts
#	aot/dist/aggrid.module.ngsummary.json
#	aot/dist/baseComponentFactory.ngsummary.json
#	aot/dist/interfaces.ngsummary.json
#	aot/dist/ng2ComponentFactory.ngsummary.json
#	aot/dist/ng2FrameworkComponentWrapper.ngsummary.json
#	aot/dist/ng2FrameworkFactory.ngsummary.json
#	aot/main.ngsummary.json
#	aot/src/agGridColumn.ngfactory.ts
#	aot/src/agGridColumn.ngsummary.json
#	aot/src/agGridNg2.ngfactory.ts
#	aot/src/agGridNg2.ngsummary.json
#	aot/src/aggrid.module.ngfactory.ts
#	aot/src/aggrid.module.ngsummary.json
#	aot/src/baseComponentFactory.ngsummary.json
#	aot/src/interfaces.ngsummary.json
#	aot/src/ng2ComponentFactory.ngsummary.json
#	aot/src/ng2FrameworkComponentWrapper.ngsummary.json
#	aot/src/ng2FrameworkFactory.ngsummary.json
2017-09-01 14:02:24 +01:00
Sean Landsman
73cc989512 AG-730 New example for redux 2017-08-31 17:17:26 +01:00
Alberto
5a45846cb7 Release 13.0.1 2017-08-29 15:27:33 +02:00
Petyo Ivanov
2d8d5b125e Removed legacy padding 2017-08-29 13:34:18 +03:00
Alberto
818b7798ee Merge branch 'latest' into 13.0.0
# Conflicts:
#	package.json
2017-08-25 16:59:25 +02:00
Sean Landsman
15ba8d7e60 Rename cellFormatter to valueFormatter 2017-08-23 14:04:13 +01:00
Alberto
eab958c3e9 Releasing 13.0.0 2017-08-23 11:35:39 +01:00
Sean Landsman
3a17b7f638 AG-668 Update all README.md to point to appropriate plunker/seed 2017-08-21 11:45:09 +01:00
Sean Landsman
734d39e2d7 AG-676 Move framework examples into parent folder for easier exclusion 2017-08-17 11:04:12 +01:00
Sean Landsman
0d7cace354 Add example for keypress in editors
https://github.com/ag-grid/ag-grid-react/issues/60
2017-08-10 16:02:03 +01:00
Sean Landsman
fa0881bfcf Merge remote-tracking branch 'origin/latest' into latest 2017-08-10 15:51:05 +01:00
Sean Landsman
62b9e3582a Add example for keypress in editors
https://github.com/ag-grid/ag-grid-react/issues/60
2017-08-10 15:50:54 +01:00
Petyo Ivanov
949797d4be rename repo from ceolter to ag-grid 2017-08-04 12:23:47 +01:00
Sean Landsman
a869fe3819 CI Work 2017-08-02 13:48:39 +01:00
Sean Landsman
c611af4f39 CI Work 2017-08-02 13:15:55 +01:00
Sean Landsman
7cab3190ae CI Work 2017-08-02 12:19:07 +01:00
Sean Landsman
71fe653fcb CI Work 2017-08-02 11:55:18 +01:00
Sean Landsman
ba1c213ce0 Change selectAll to use refs to expand on example 2017-07-27 08:17:15 +01:00
Sean Landsman
46217c9ad7 Fix sorting issue 2017-07-26 12:10:12 +01:00
Sean Landsman
017642e4d7 AG-643 Tidy React examples 2017-07-25 12:47:47 +01:00
Sean Landsman
79b0eda61b AG-643 Tidy React examples 2017-07-25 12:47:07 +01:00
Sean Landsman
a70f248af5 AG-642 Remove deprecation warning in preparation for 16.x 2017-07-25 12:46:21 +01:00
Alberto
32142b435b v12 Hot fixes 2017-07-21 12:10:00 +02:00
Alberto
d71781899d AG-618 Fixing floating filter issue. Also allowing for gulp watch of Angular and React 2017-07-20 13:59:16 +02:00
Sean Landsman
9560f86bf5 Updated readme 2017-07-19 10:30:28 +01:00
Alberto
9f4b270884 New release branch, everything compiles 2017-07-13 11:25:34 +01:00
John Masterson
e5627d8b9f Added links to ReadMe 2017-07-11 17:07:57 +01:00
Alberto
f8f0c21af2 Version 11.0.0 2017-06-26 16:40:27 +02:00
Sean Landsman
b54d549959 AG-528 Document and use in examples overriding of style in child (react component) divs 2017-06-14 15:32:09 +01:00
Sean Landsman
464a0ea9f4 AG-529 Implement improvements - esp around property changes 2017-06-14 13:15:54 +01:00
Sean Landsman
675cbe497c AG-538 Upgrade to React 15x
AG-539 React rich grid example - fix bugs
2017-06-13 18:15:05 +01:00
Sean Landsman
a4dbbf529d AG-534 Make use of new data retrieval & updating in trader dashboard 2017-06-13 15:17:30 +01:00
159 changed files with 1538 additions and 11374 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
/node_modules
/dist
package-lock.json
*.nosync

View File

@@ -1,22 +1,18 @@
ag-Grid React Example
==============
Examples of running ag-Grid inside React application.
See the [www.ag-grid.com](http://www.ag-grid.com).
There are two examples:
## Examples
1. standard - shows a typical grid demonstrating many ag-Grid features
2. large - shows a very large grid (767 columns and 1,000 rows) using React cell renderers
See [www.ag-grid.com](http://www.ag-grid.com) for full documentation and examples.
Building
==============
To build:
- `npm install`
- `npm install webpack -g`
- `npm run standard` or `npm run large`
- `npm run examples`, `npm run large` or `npm run trader`
- navigate to localhost:8080

View 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
}
};

View 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,
}
};

View File

@@ -0,0 +1,46 @@
const path = require('path');
const SRC_DIR = path.resolve(__dirname, '../src-trader-dashboard');
module.exports = {
mode: 'production',
entry: SRC_DIR + "/index.js",
output: {
path: path.resolve(__dirname, '../'),
filename: "dist/react-trader.js"
},
module: {
rules: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.js$|\.jsx$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['@babel/preset-react', '@babel/preset-env'],
plugins: [
require('@babel/plugin-proposal-function-bind'),
require('@babel/plugin-proposal-class-properties')
]
}
}
]
},
resolve: {
alias: {
"@ag-grid-community/core": path.resolve('./node_modules/@ag-grid-community/core'),
"ag-grid-enterprise": path.resolve('./node_modules/ag-grid-enterprise'),
react: path.resolve('./node_modules/react')
},
extensions: ['.js', '.jsx']
},
performance: {
hints: false
},
devServer: {
port: 8080,
}
};

26
gulpfile.js Normal file
View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,30 @@
{
"name": "ag-grid-react-example",
"version": "10.0.0",
"version": "23.0.0",
"description": "Example Reach applicaiton using ag-Grid.",
"main": "dist/ag-grid-react-example.js",
"scripts": {
"trader": "webpack-dev-server --content-base src-trader-dashboard/ --config webpack.config.trader.js --progress --colors --hot --inline",
"examples": "webpack-dev-server --content-base src/ --config webpack.config.examples.js --progress --colors --hot --inline",
"large": "webpack-dev-server --config webpack.config.large.js --progress --colors --hot --inline",
"trader": "webpack-dev-server --content-base src-trader-dashboard/ --config config/webpack.config.trader.js --mode development --open",
"examples": "webpack-dev-server --content-base src-examples/ --config config/webpack.config.examples.js --mode development --open",
"large": "webpack-dev-server --content-base src-large-data/ --config config/webpack.config.large.js --mode development --open",
"clean": "rimraf dist",
"mkdirs": "mkdirp dist/trader/dist dist/examples/dist",
"copy-examples": "ncp images dist/examples/images && ncp src/index.html dist/examples/index.html && ncp dist/react-examples.js dist/examples/dist/react-examples.js && ncp src dist/examples/src",
"copy-examples": "ncp src-examples/images dist/examples/images && ncp src-examples/index.html dist/examples/index.html && ncp dist/react-examples.js dist/examples/dist/react-examples.js && ncp src-examples/ dist/examples/src",
"copy-trader": "ncp src-trader-dashboard/index.html dist/trader/index.html && ncp dist/react-trader.js dist/trader/dist/react-trader.js",
"copy": "npm run copy-examples && npm run copy-trader",
"build-examples": "webpack --config webpack.config.examples.js --progress --profile --bail",
"build-dashboard": "webpack --config webpack.config.trader.js --progress --profile --bail",
"build-large": "webpack --config config/webpack.config.large.js --progress --profile --bail",
"build-examples": "webpack --config config/webpack.config.examples.js --progress --profile --bail",
"build-dashboard": "webpack --config config/webpack.config.trader.js --progress --profile --bail",
"build-all": "npm run build-examples && npm run build-dashboard",
"build": "npm run clean && npm run mkdirs && npm run build-all && npm run copy",
"copy-to-docs": "ncp dist/examples ../ag-grid-docs/src/react-examples/examples && ncp dist/trader ../ag-grid-docs/src/react-examples/trader",
"build-to-docs": "npm run build && npm run copy-to-docs"
"start": "npm run examples",
"test": "./ts-tests/runTsTests.sh"
},
"repository": {
"type": "git",
"url": "https://github.com/ceolter/ag-grid-react-example.git"
"url": "https://github.com/ag-grid/ag-grid-react-example.git"
},
"private": true,
"keywords": [
"react",
"grid",
@@ -32,38 +34,43 @@
"author": "Niall Crosby <niall.crosby@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/ceolter/ag-grid-react-example/issues"
"url": "https://github.com/ag-grid/ag-grid-react-example/issues"
},
"homepage": "http://www.ag-grid.com/",
"devDependencies": {
"babel-core": "6.24.x",
"babel-loader": "6.4.x",
"babel-preset-es2015": "6.24.x",
"babel-preset-react": "6.24.x",
"babel-preset-stage-0": "6.24.x",
"babel-preset-stage-1": "6.24.x",
"css-loader": "0.23.x",
"@ag-grid-community/core": "~23.0.0",
"@babel/core": "7.4.4",
"@babel/plugin-proposal-class-properties": "7.4.4",
"@babel/plugin-proposal-function-bind": "7.2.0",
"@babel/preset-env": "7.4.4",
"@babel/preset-react": "7.0.0",
"@types/react": "16.9.2",
"@types/react-dom": "16.9.0",
"babel-loader": "8.0.6",
"css-loader": "2.1.1",
"file-loader": "3.0.1",
"gulp": "3.9.1",
"merge2": "1.2.3",
"mkdirp": "0.5.1",
"ncp": "2.0.0",
"rimraf": "2.5.x",
"style-loader": "0.13.x",
"webpack": "1.12.x",
"webpack-dev-server": "1.14.x"
"prop-types": "15.7.2",
"rimraf": "2.6.3",
"style-loader": "0.23.1",
"typescript": "3.4.5",
"webpack": "4.31.0",
"webpack-cli": "3.3.2",
"webpack-dev-server": "3.4.1"
},
"dependencies": {
"bootstrap": "3.3.7",
"@ag-grid-enterprise/all-modules": "~23.0.0",
"@ag-grid-community/react": "~23.0.0",
"bootstrap": "4.4.1",
"d3": "4.9.1",
"file-loader": "0.11.1",
"lodash": "4.17.4",
"react": "15.5.x",
"react-dom": "15.5.x",
"react-redux": "5.0.x",
"redux": "3.6.x",
"url-search-params-polyfill": "1.2.0",
"ag-grid": "10.1.x",
"ag-grid-enterprise": "10.1.x",
"ag-grid-react": "10.1.x"
"lodash": "4.17.11",
"react": "16.8.6",
"react-dom": "16.8.6",
"react-redux": "7.0.3",
"react-router-dom": "5.0.0",
"redux": "4.0.1"
}
}
}

37
src-examples/App.jsx Normal file
View File

@@ -0,0 +1,37 @@
import React, {Component} from "react";
import {Redirect, Route, Switch} from "react-router-dom";
import NavItem from "./NavItem";
import RichGridDeclarativeExample from "./richGridDeclarativeExample/RichGridDeclarativeExample";
import SimpleReduxDynamicExample from "./simpleReduxDynamicComponentExample/SimpleReduxExample";
import SimpleReduxHookExample from "./simpleReduxHooksExample/SimpleReduxHookExample";
const SideBar = () => (
<div style={{float: "left", width: 335, marginRight: 25}}>
<ul className="nav nav-pills">
<NavItem to='/rich-grid-declarative'>Rich Grid with Declarative Markup</NavItem>
<NavItem to='/simple-redux-dynamic'>Simple Redux Dynamic Component Example</NavItem>
<NavItem to='/simple-redux-hook'>Simple React Hook Component Example</NavItem>
</ul>
</div>
);
class App extends Component {
render() {
return (
<div style={{display: "inline-block", width: "100%"}}>
<SideBar/>
<div style={{float: "left"}}>
<Switch>
<Redirect from="/" exact to="/rich-grid-declarative"/>
<Route exact path='/rich-grid-declarative' component={RichGridDeclarativeExample}/>
<Route exact path='/simple-redux-dynamic' component={SimpleReduxDynamicExample}/>
<Route exact path='/simple-redux-hook' component={SimpleReduxHookExample}/>
</Switch>
</div>
</div>
)
}
}
export default App

20
src-examples/NavItem.jsx Normal file
View File

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

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 606 B

After

Width:  |  Height:  |  Size: 606 B

View File

Before

Width:  |  Height:  |  Size: 128 B

After

Width:  |  Height:  |  Size: 128 B

View File

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 256 B

View File

Before

Width:  |  Height:  |  Size: 99 B

After

Width:  |  Height:  |  Size: 99 B

View File

Before

Width:  |  Height:  |  Size: 99 B

After

Width:  |  Height:  |  Size: 99 B

View File

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View File

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 228 B

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 154 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 136 B

After

Width:  |  Height:  |  Size: 136 B

View File

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 154 B

View File

Before

Width:  |  Height:  |  Size: 89 B

After

Width:  |  Height:  |  Size: 89 B

View File

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 227 B

View File

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 97 B

View File

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 222 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 739 B

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 883 B

After

Width:  |  Height:  |  Size: 883 B

View File

Before

Width:  |  Height:  |  Size: 902 B

After

Width:  |  Height:  |  Size: 902 B

View File

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 953 B

View File

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 394 B

View File

Before

Width:  |  Height:  |  Size: 893 B

After

Width:  |  Height:  |  Size: 893 B

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 570 B

View File

@@ -3,49 +3,64 @@
<head>
<meta charset="utf-8">
<script type="text/javascript" src="dist/react-examples.js" charset="utf-8"></script>
<script type="text/javascript" src="../dist/react-examples.js" charset="utf-8"></script>
<!-- Example uses font awesome icons -->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" rel="stylesheet">
<style>
html, body {
height: 100%;
}
body {
line-height: 1
}
h1 {
font-size: 1.5rem;
}
div.card-body > a {
margin-top: 5px
}
.btn-primary {
margin-right: 5px;
}
button {
margin-left: 4px;
margin-right: 4px;
}
.align-right {
text-align: right
}
.customHeaderMenuButton {
margin-top: 5px;
margin-left: 4px;
float: left;
}
.customHeaderLabel {
margin-left: 5px;
margin-top: 3px;
float: left;
}
.customSortDownLabel {
float: left;
margin-left: 10px;
margin-top: 5px;
}
.customSortUpLabel {
float: left;
margin-left: 3px;
margin-top: 4px;
}
.customSortRemoveLabel {
float: left;
font-size: 11px;
margin-left: 3px;
margin-top: 6px;
}
.active {
@@ -58,21 +73,19 @@
.customHeaderLabel {
margin-left: 5px;
margin-top: 3px;
float: left;
}
.customExpandButton {
float: right;
margin-top: 5px;
margin-left: 3px;
}
.expanded {
animation-name: toExpanded;
animation-duration: 1s;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
@@ -80,22 +93,22 @@
color: cornflowerblue;
animation-name: toCollapsed;
animation-duration: 1s;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
@keyframes toExpanded {
from {
color: cornflowerblue;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
to {
color: black;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
}
@@ -103,14 +116,14 @@
@keyframes toCollapsed {
from {
color: black;
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(180deg); /* IE 9 */
-webkit-transform: rotate(180deg); /* Chrome, Safari, Opera */
transform: rotate(180deg);
}
to {
color: cornflowerblue;
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(0deg); /* IE 9 */
-webkit-transform: rotate(0deg); /* Chrome, Safari, Opera */
transform: rotate(0deg);
}
}
@@ -120,4 +133,4 @@
<body>
<div id="app"></div>
</body>
</html>
</html>

25
src-examples/index.js Normal file
View File

@@ -0,0 +1,25 @@
'use strict';
import React from "react";
import {render} from "react-dom";
import {BrowserRouter} from "react-router-dom";
import "@ag-grid-enterprise/all-modules/dist/styles/ag-grid.css";
import "@ag-grid-enterprise/all-modules/dist/styles/ag-theme-balham.css";
import "../node_modules/bootstrap/dist/css/bootstrap.css";
import App from "./App";
// only required when using enterprise features
// import {LicenseManager} from "@ag-grid-enterprise/all-modules";
// LicenseManager.setLicenseKey("<your license key>");
document.addEventListener('DOMContentLoaded', () => {
render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.querySelector('#app')
);
});

View File

@@ -1,10 +1,11 @@
import React from 'react';
import React from "react";
import * as PropTypes from "prop-types";
// Date Component to be used in the date filter.
// This is a very simple example of how a React component can be plugged as a DateComponentFramework
// as you can see, the only requirement is that the React component implements the required methods
// getDate and setDate and that it calls back into props.onDateChanged every time that the date changes.
export default class MyReactDateComponent extends React.Component {
export default class DateComponent extends React.Component {
constructor(props) {
super(props);
@@ -27,7 +28,7 @@ export default class MyReactDateComponent extends React.Component {
render() {
//Inlining styles to make simpler the component
let filterStyle = {
margin:'2px'
margin: '2px'
};
let ddStyle = {
width: '30px'
@@ -36,7 +37,7 @@ export default class MyReactDateComponent extends React.Component {
width: '30px'
};
let yyyyStyle = {
width: '60px'
width: '40px'
};
let resetStyle = {
padding: '2px',
@@ -50,9 +51,12 @@ export default class MyReactDateComponent extends React.Component {
return (
<div style={filterStyle}>
<span style={resetStyle} onClick={this.resetDate.bind(this)}>x</span>
<input onInput = {this.onDateChanged.bind(this)} ref="dd" placeholder="dd" style={ddStyle} value={this.state.textBoxes.dd} maxLength="2"/>/
<input onInput = {this.onDateChanged.bind(this)} ref="mm" placeholder="mm" style={mmStyle} value={this.state.textBoxes.mm} maxLength="2"/>/
<input onInput = {this.onDateChanged.bind(this)} ref="yyyy" placeholder="yyyy" style={yyyyStyle} value={this.state.textBoxes.yyyy} maxLength="4"/>
<input onChange={this.onDateChanged.bind(this)} ref="dd" placeholder="dd" style={ddStyle}
value={this.state.textBoxes.dd} maxLength="2"/>/
<input onChange={this.onDateChanged.bind(this)} ref="mm" placeholder="mm" style={mmStyle}
value={this.state.textBoxes.mm} maxLength="2"/>/
<input onChange={this.onDateChanged.bind(this)} ref="yyyy" placeholder="yyyy" style={yyyyStyle}
value={this.state.textBoxes.yyyy} maxLength="4"/>
</div>
);
}
@@ -61,20 +65,20 @@ export default class MyReactDateComponent extends React.Component {
// METHODS REQUIRED BY AG-GRID
//*********************************************************************************
getDate (){
getDate() {
//ag-grid will call us here when in need to check what the current date value is hold by this
//component.
return this.state.date;
}
setDate (date){
setDate(date) {
//ag-grid will call us here when it needs this component to update the date that it holds.
this.setState({
date:date,
textBoxes:{
dd: date.getDate(),
mm: date.getMonth() + 1,
yyyy: date.getFullYear()
date,
textBoxes: {
dd: date ? date.getDate() : '',
mm: date ? date.getMonth() + 1 : '',
yyyy: date ? date.getFullYear() : ''
}
})
}
@@ -83,10 +87,10 @@ export default class MyReactDateComponent extends React.Component {
// LINKS THE INTERNAL STATE AND AG-GRID
//*********************************************************************************
updateAndNotifyAgGrid (date, textBoxes){
this.setState ({
updateAndNotifyAgGrid(date, textBoxes) {
this.setState({
date: date,
textBoxes:textBoxes
textBoxes: textBoxes
},
//Callback after the state is set. This is where we tell ag-grid that the date has changed so
//it will proceed with the filtering and we can then expect ag-Grid to call us back to getDate
@@ -99,23 +103,23 @@ export default class MyReactDateComponent extends React.Component {
// LINKING THE UI, THE STATE AND AG-GRID
//*********************************************************************************
resetDate (){
resetDate() {
let date = null;
let textBoxes = {
dd : '',
mm : '',
yyyy : '',
dd: '',
mm: '',
yyyy: '',
};
this.updateAndNotifyAgGrid(date, textBoxes)
}
onDateChanged () {
onDateChanged() {
let date = this.parseDate(this.refs.dd.value, this.refs.mm.value, this.refs.yyyy.value);
let textBoxes = {
dd : this.refs.dd.value,
mm : this.refs.mm.value,
yyyy : this.refs.yyyy.value,
dd: this.refs.dd.value,
mm: this.refs.mm.value,
yyyy: this.refs.yyyy.value,
};
this.updateAndNotifyAgGrid(date, textBoxes)
@@ -125,7 +129,7 @@ export default class MyReactDateComponent extends React.Component {
// INTERNAL LOGIC
//*********************************************************************************
parseDate (dd, mm, yyyy){
parseDate(dd, mm, yyyy) {
//If any of the three input date fields are empty, stop and return null
if (dd.trim() === '' || mm.trim() === '' || yyyy.trim() === '') {
return null;
@@ -138,7 +142,7 @@ export default class MyReactDateComponent extends React.Component {
let date = new Date(year, month - 1, day);
//If the date is not valid
if (isNaN(date.getTime())){
if (isNaN(date.getTime())) {
return null;
}
@@ -150,7 +154,7 @@ export default class MyReactDateComponent extends React.Component {
//If the javascript date parts don't match the provided fields, we assume that the input is non
//sensical... ie: Day=-1 or month=14, if this is the case, we return null
//This also protects us from non sensical dates like dd=31, mm=2 of any year
if (date.getDate() != day || date.getMonth() + 1 != month || date.getFullYear() != year){
if (date.getDate() != day || date.getMonth() + 1 != month || date.getFullYear() != year) {
return null;
}
@@ -162,6 +166,6 @@ export default class MyReactDateComponent extends React.Component {
// which is the grid passing you the params for the cellRenderer.
// this piece is optional. the grid will always pass the 'params'
// props, so little need for adding this validation meta-data.
MyReactDateComponent.propTypes = {
params: React.PropTypes.object
DateComponent.propTypes = {
params: PropTypes.object
};

View File

@@ -1,31 +1,36 @@
import React from 'react';
import * as PropTypes from 'prop-types';
// Header component to be used as default for all the columns.
export default class MyReactHeaderGroupComponent extends React.Component {
export default class HeaderGroupComponent extends React.Component {
constructor(props) {
super(props);
this.props.columnGroup.getOriginalColumnGroup().addEventListener('expandedChanged', this.onExpandChanged.bind(this));
this.state = {
expanded:null
}
expanded: null
};
}
componentDidMount() {
this.onExpandChanged();
}
render() {
let arrowClassName = "customExpandButton " + (this.state.expanded ? " expanded": " collapsed");
let arrowClassName = "customExpandButton " + (this.state.expanded ? " expanded" : " collapsed");
return <div>
<div className="customHeaderLabel"> {this.props.displayName}</div>
<div onClick={this.expandOrCollapse.bind(this)} className={arrowClassName}><i className="fa fa-arrow-right" /></div>
<div onClick={this.expandOrCollapse.bind(this)} className={arrowClassName}><i
className="fa fa-arrow-right"/></div>
</div>
}
expandOrCollapse (){
expandOrCollapse() {
this.props.setExpanded(!this.state.expanded);
};
onExpandChanged (){
onExpandChanged() {
this.setState({
expanded: this.props.columnGroup.getOriginalColumnGroup().isExpanded()
})
@@ -36,6 +41,6 @@ export default class MyReactHeaderGroupComponent extends React.Component {
// which is the grid passing you the params for the cellRenderer.
// this piece is optional. the grid will always pass the 'params'
// props, so little need for adding this validation meta-data.
MyReactHeaderGroupComponent.propTypes = {
params: React.PropTypes.object
HeaderGroupComponent.propTypes = {
params: PropTypes.object
};

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,3 @@
.ag-react-container {
display: block;
}
.ag-cell {
padding-top: 2px !important;
padding-bottom: 2px !important;

View File

@@ -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-times"/>',
filter: '<i class="fa fa-filter"/>',
sortAscending: '<i class="fa fa-long-arrow-alt-down"/>',
sortDescending: '<i class="fa fa-long-arrow-alt-up"/>',
groupExpanded: '<i class="far fa-minus-square"/>',
groupContracted: '<i class="far fa-plus-square"/>'
}
};
}
/* 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&nbsp;</label>
<input type="checkbox" id="sideBarToggle" onChange={this.onToggleSidebar} style={{ marginRight: 5 }} />
</div>
<div style={{ float: "right", marginLeft: 20 }}>
<label htmlFor="quickFilter">Quick Filter:&nbsp;</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>
);
}
}

View File

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

View File

@@ -1,14 +1,15 @@
import React from 'react';
import * as PropTypes from 'prop-types';
import RefData from './RefData';
export default class SkillsCellRenderer extends React.Component {
render() {
var skills = [];
var rowData = this.props.data;
RefData.IT_SKILLS.forEach( (skill) => {
const skills = [];
const rowData = this.props.data;
RefData.IT_SKILLS.forEach((skill) => {
if (rowData && rowData.skills && rowData.skills[skill]) {
skills.push(<img key={skill} src={'images/skills/' + skill + '.png'} width={16} title={skill} />);
skills.push(<img key={skill} src={'images/skills/' + skill + '.png'} width={16} title={skill}/>);
}
});
@@ -22,5 +23,5 @@ export default class SkillsCellRenderer extends React.Component {
// this piece is optional. the grid will always pass the 'params'
// props, so little need for adding this validation meta-data.
SkillsCellRenderer.propTypes = {
params: React.PropTypes.object
params: PropTypes.object
};

View File

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

View File

@@ -0,0 +1,89 @@
import React from "react";
import * as PropTypes from "prop-types";
// Header component to be used as default for all the columns.
export default class SortableHeaderComponent extends React.Component {
constructor(props) {
super(props);
// this.sortChanged = this.onSortChanged.bind(this);
this.props.column.addEventListener('sortChanged', this.onSortChanged);
//The state of this component contains the current sort state of this column
//The possible values are: 'asc', 'desc' and ''
this.state = {
sorted: ''
}
}
componentWillUnmount() {
this.props.column.removeEventListener('sortChanged', this.onSortChanged);
}
render() {
let sortElements = [];
if (this.props.enableSorting) {
let downArrowClass = "customSortDownLabel " + (this.state.sorted === 'desc' ? " active" : "");
let upArrowClass = "customSortUpLabel " + (this.state.sorted === 'asc' ? " active" : "");
let removeArrowClass = "customSortRemoveLabel " + (this.state.sorted === '' ? " active" : "");
sortElements.push(<div key={`up${this.props.displayName}`} className={downArrowClass}
onClick={this.onSortRequested.bind(this, 'desc')}><i
className="fa fa-long-arrow-alt-down"/></div>);
sortElements.push(<div key={`down${this.props.displayName}`} className={upArrowClass}
onClick={this.onSortRequested.bind(this, 'asc')}><i
className="fa fa-long-arrow-alt-up"/></div>);
sortElements.push(<div key={`minus${this.props.displayName}`} className={removeArrowClass}
onClick={this.onSortRequested.bind(this, '')}><i
className="fa fa-times"/></div>)
}
let menuButton = null;
if (this.props.enableMenu) {
menuButton =
<div ref="menuButton" className="customHeaderMenuButton" onClick={this.onMenuClick.bind(this)}><i
className={"fa " + this.props.menuIcon}/></div>
}
return <div>
{menuButton}
<div className="customHeaderLabel">{this.props.displayName}</div>
{sortElements}
</div>
}
onSortRequested(order, event) {
this.props.setSort(order, event.shiftKey);
};
onSortChanged = () => {
if (this.props.column.isSortAscending()) {
this.setState({
sorted: 'asc'
})
} else if (this.props.column.isSortDescending()) {
this.setState({
sorted: 'desc'
})
} else {
this.setState({
sorted: ''
})
}
};
onMenuClick() {
this.props.showColumnMenu(this.refs.menuButton);
};
}
// the grid will always pass in one props called 'params',
// which is the grid passing you the params for the cellRenderer.
// this piece is optional. the grid will always pass the 'params'
// props, so little need for adding this validation meta-data.
SortableHeaderComponent.propTypes = {
params: PropTypes.object
};

View File

@@ -0,0 +1,64 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import {AgGridReact} from "@ag-grid-community/react";
import {AllModules} from "@ag-grid-enterprise/all-modules";
import PriceRenderer from "./PriceRenderer";
/*
* This component serves to display the row data (provided by redux)
*/
class GridComponent extends Component {
constructor(props) {
super(props);
this.state = {
columnDefs: [
{
field: 'symbol'
},
{
field: 'price',
cellClass: 'align-right',
cellRendererFramework: PriceRenderer
}
]
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
// row data will be provided via redux on this.props.rowData
render() {
return (
<div style={{height: 400, width: 900, marginTop: 15}}
className="ag-theme-balham">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.props.rowData}
modules={AllModules}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
)
}
}
// pull off row data changes
export default connect(
(state) => {
return {
rowData: state.rowData
}
}
)(GridComponent);

View File

@@ -0,0 +1,83 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import {setCurrency, updateRowData} from "./gridDataActions";
/*
* This component serves both to host the demo controls, which in turn will drive row data state changes
*/
class HeaderComponent extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// provide the initial data to the store (which in turn will populate the grid)
this.props.dispatch(updateRowData(this.createRowData()));
}
setCurrency(currencySymbol, exchangeRate) {
this.props.dispatch(setCurrency(currencySymbol, exchangeRate));
}
render() {
return (
<div style={{marginTop: 15}}>
<button onClick={this.setCurrency.bind(this, '£', 1)} className="btn btn-primary">Set Currency to GBP</button>
<button onClick={this.setCurrency.bind(this, '$', 1.29)} className="btn btn-primary">Set Currency to USD</button>
</div>
)
}
// the following methods are for creating dummy row data
createRowData() {
let rowData = [];
for (let i = 0; i < 14; i++) {
let newItem = this.createItem();
rowData.push(newItem);
}
return rowData;
}
createItem() {
return {
symbol: this.createUniqueRandomSymbol(),
price: Math.floor(Math.random() * 100)
};
}
// creates a unique symbol, eg 'ADG' or 'ZJD'
createUniqueRandomSymbol() {
let symbol;
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let isUnique = false;
while (!isUnique) {
symbol = '';
// create symbol
for (let i = 0; i < 3; i++) {
symbol += possible.charAt(Math.floor(Math.random() * possible.length));
}
// check uniqueness
isUnique = true;
this.props.rowData.forEach(function (oldItem) {
if (oldItem.symbol === symbol) {
isUnique = false;
}
});
}
return symbol;
}
}
// pull off row data
export default connect(
(state) => {
return {
rowData: state.rowData
}
}
)(HeaderComponent);

View File

@@ -0,0 +1,45 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import FontContext from './fontContext'
class PriceRenderer extends Component {
constructor(props) {
super(props);
this.state = {
convertedValue: this.applyExchangeRate(props.exchangeRate, props.value)
};
}
componentWillReceiveProps(nextProps) {
this.setState({
convertedValue: this.applyExchangeRate(nextProps.exchangeRate, nextProps.value)
})
}
render() {
return (
<FontContext.Consumer>
{fontWeight => <span
style={{fontWeight}}> {this.props.currencySymbol}{this.state.convertedValue}</span>}
</FontContext.Consumer>
);
}
applyExchangeRate = (exchangeRate, value) => {
return parseFloat(value * exchangeRate).toFixed(2); // simplified/naive exchange rate implementation!
}
}
export default connect(
(state) => {
return {
currencySymbol: state.currencySymbol,
exchangeRate: state.exchangeRate
}
},
null,
null,
{forwardRef: true} // must be supplied for react/redux when using AgGridReact
)(PriceRenderer);

View File

@@ -1,14 +1,14 @@
import React, {Component} from "react";
import {Provider} from "react-redux";
import {createStore} from "redux";
// take this line out if you do not want to use ag-Grid-Enterprise
import "ag-grid-enterprise";
import HeaderComponent from "./HeaderComponent";
import GridComponent from "./GridComponent";
import gridData from "./gridDataReducer";
import FontContext from './fontContext'
let store = createStore(gridData);
/*
@@ -18,21 +18,17 @@ let store = createStore(gridData);
export default class SimpleReduxExample extends Component {
constructor(props) {
super(props);
this.setGroupingEnabled = this.setGroupingEnabled.bind(this);
}
setGroupingEnabled(enabled) {
this.grid.setGroupingEnabled(enabled);
}
render() {
return (
<Provider store={store}>
<div>
<h1>Simple Redux Example using ag-Grid's deltaRowMode</h1>
<HeaderComponent setGroupingEnabled={this.setGroupingEnabled} />
<GridComponent ref={ grid => { this.grid = grid ? grid.getWrappedInstance() : null }} />
<h1>Simple Redux Example using Connected React Components</h1>
<HeaderComponent/>
<FontContext.Provider value="bold">
<GridComponent/>
</FontContext.Provider>
</div>
</Provider>
)

View File

@@ -0,0 +1,3 @@
import React from "react";
export default React.createContext('normal');

View 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
}
}

View File

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

View 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>
)
}

View 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}/>;
})

View 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()}/>;
})

View File

@@ -1,13 +1,13 @@
import React, {Component} from "react";
export default class CurrencyRenderer extends Component {
export default class PriceRenderer extends Component {
constructor(props) {
super(props);
}
render() {
return (
<span style={this.props.style}>{this.props.value}</span>
<span>{this.props.value}</span>
);
}
};
}

View File

@@ -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>
)
}

View 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
}
}

View 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;
};

View File

@@ -5,7 +5,7 @@
<head>
<meta charset="utf-8">
<script type="text/javascript" src="dist/bundle.js" charset="utf-8"></script>
<script type="text/javascript" src="../dist/react-large.js" charset="utf-8"></script>
<!-- Example uses font awesome icons -->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</head>

View File

@@ -3,9 +3,9 @@
import ReactDOM from 'react-dom';
import React from 'react';
import LargeGrid from './largeGrid.jsx';
// is there a better way of doing this?
import 'ag-grid-root/dist/styles/ag-grid.css';
import 'ag-grid-root/dist/styles/theme-fresh.css';
import '@ag-grid-community/core/dist/styles/ag-grid.css';
import '@ag-grid-community/core/dist/styles/ag-theme-balham.css';
// waiting for dom to load before booting react. we could alternatively
// put the index.js reference at the end fo the index.html, but i prefer this way.

View File

@@ -1,13 +1,14 @@
import React from 'react';
import {reactCellRendererFactory} from 'ag-grid-react';
import React, {Component} from 'react';
import SimpleCellRenderer from './simpleCellRenderer.jsx';
import {AgGridReact} from '@ag-grid-community/react';
import {AgGridReact} from 'ag-grid-react';
// for community features
import {AllModules} from "@ag-grid-enterprise/all-modules";
// put this line in to use ag-Grid enterprise
// import 'ag-grid-enterprise';
// for enterprise features
// import {AllModules} from "@ag-grid-enterprise/all-modules";
export default class MyApp extends React.Component {
export default class MyApp extends Component {
constructor() {
super();
@@ -22,22 +23,22 @@ export default class MyApp extends React.Component {
createColumnNames() {
// creates column names by iterating the alphabet twice, eg {'aa','ab','ac',.....'zz'}
var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
this.columnNames = [];
alphabet.forEach( letter1 => {
alphabet.forEach( letter2 => {
alphabet.forEach(letter1 => {
alphabet.forEach(letter2 => {
this.columnNames.push(letter1 + letter2);
});
});
}
createRowData() {
var rowData = [];
const rowData = [];
for (var i = 0; i<1000; i++) {
var item = {};
this.columnNames.forEach( colName => {
item[colName] = '('+colName.toUpperCase()+','+i+')'
for (let i = 0; i < 1000; i++) {
const item = {};
this.columnNames.forEach(colName => {
item[colName] = '(' + colName.toUpperCase() + ',' + i + ')'
});
rowData.push(item);
}
@@ -46,9 +47,9 @@ export default class MyApp extends React.Component {
}
createColumnDefs() {
var columnDefs = [];
const columnDefs = [];
this.columnNames.forEach( colName => {
this.columnNames.forEach(colName => {
columnDefs.push({
headerName: colName.toUpperCase(),
field: colName,
@@ -62,8 +63,8 @@ export default class MyApp extends React.Component {
render() {
return (
<div style={{height: '100%'}} className="ag-fresh">
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} />
<div style={{height: '100%'}} className="ag-theme-balham">
<AgGridReact columnDefs={this.state.columnDefs} rowData={this.state.rowData} modules={AllModules}/>
</div>
);
}

View File

@@ -1,4 +1,5 @@
import React from 'react';
import * as PropTypes from 'prop-types';
export default class SimpleCellRenderer extends React.Component {
render() {
@@ -11,5 +12,5 @@ export default class SimpleCellRenderer extends React.Component {
}
SimpleCellRenderer.propTypes = {
params: React.PropTypes.object
params: PropTypes.object
};

View File

@@ -1,10 +1,9 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import {AgGridReact} from "ag-grid-react";
import {AgGridReact} from "@ag-grid-community/react";
import assign from "lodash/assign";
import uniq from "lodash/uniq";
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
class FxQuoteMatrix extends Component {
constructor(props) {
@@ -16,6 +15,9 @@ class FxQuoteMatrix extends Component {
// grid events
this.onGridReady = this.onGridReady.bind(this);
// grid callbacks
this.getRowNodeId = this.getRowNodeId.bind(this);
}
onGridReady(params) {
@@ -27,45 +29,51 @@ class FxQuoteMatrix extends Component {
}
}
getRowNodeId(data) {
return data.symbol;
}
componentWillReceiveProps(nextProps) {
const newRowData = nextProps.rowData;
if (this.gridApi) {
const newRowData = nextProps.rowData;
const updatedNodes = [];
const updatedCols = [];
const updatedRows = [];
for (let i = 0; i < newRowData.length; i++) {
// note that for this use case we assume the existing and new row data have the same
// row and column order
let node = this.gridApi.getModel().getRow(i);
let newRow = newRowData[i];
for (let i = 0; i < newRowData.length; i++) {
let newRow = newRowData[i];
let currentRowNode = this.gridApi.getRowNode(newRow.symbol);
const {data} = node;
let updated = false;
for (const def of this.state.columnDefs) {
if (data[def.field] !== newRow[def.field]) {
updatedCols.push(def.field);
updated = true;
const {data} = currentRowNode;
for (const def of this.state.columnDefs) {
if (data[def.field] !== newRow[def.field]) {
updatedRows.push(newRow);
break;
}
}
}
if (updated) {
assign(data, newRow);
updatedNodes.push(node);
}
this.gridApi.updateRowData({update: updatedRows});
}
this.gridApi.refreshCells(updatedNodes, uniq(updatedCols));
}
render() {
return (
<div style={{height: 410, width: 800}}
className="ag-fresh">
className="ag-theme-balham">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
enableSorting="false"
enableFilter="false"
defaultColDef={{
sortable: false,
filter: false
}}
// callbacks
getRowNodeId={this.getRowNodeId}
modules={[ClientSideRowModelModule]}
// events
onGridReady={this.onGridReady}>
@@ -78,7 +86,7 @@ class FxQuoteMatrix extends Component {
export default connect(
(state) => {
return {
rowData: state.fxData
rowData: state ? state.fxData : null
}
}
)(FxQuoteMatrix);
)(FxQuoteMatrix);

View File

@@ -1,12 +1,12 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import {AgGridReact} from "@ag-grid-community/react";
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
import map from "lodash/map";
import difference from "lodash/difference";
import forEach from "lodash/forEach";
import includes from "lodash/includes";
import assign from "lodash/assign";
import ExchangeService from "../services/ExchangeService.jsx";
@@ -24,22 +24,22 @@ export default class extends Component {
{
field: 'price',
headerName: 'Price',
cellFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
valueFormatter: this.numberFormatter,
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellStyle: {'text-align': 'right'}
},
{
field: 'bid',
headerName: 'Bid',
cellFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
valueFormatter: this.numberFormatter,
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellStyle: {'text-align': 'right'}
},
{
field: 'ask',
headerName: 'Ask',
cellFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
valueFormatter: this.numberFormatter,
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellStyle: {'text-align': 'right'}
}
]
@@ -51,6 +51,9 @@ export default class extends Component {
this.onGridReady = this.onGridReady.bind(this);
this.onSelectionChanged = this.onSelectionChanged.bind(this);
// grid callbacks
this.getRowNodeId = this.getRowNodeId.bind(this);
// component events
this.updateSymbol = this.updateSymbol.bind(this);
}
@@ -69,7 +72,7 @@ export default class extends Component {
// make realistic - call in a batch
let rowData = map(this.props.selectedExchange.supportedStocks, symbol => this.exchangeService.getTicker(symbol));
this.gridApi.addItems(rowData);
this.gridApi.updateRowData({add: rowData});
// select the first symbol to show the chart
this.gridApi.getModel().getRow(0).setSelected(true);
@@ -77,6 +80,10 @@ export default class extends Component {
this.gridApi.sizeColumnsToFit();
}
getRowNodeId(data) {
return data.symbol;
}
onSelectionChanged() {
let selectedNode = this.gridApi.getSelectedNodes()[0];
this.props.onSelectionChanged(selectedNode ? selectedNode.data.symbol : null);
@@ -108,25 +115,25 @@ export default class extends Component {
this.exchangeService.removeSubscriber(this.updateSymbol, symbol);
});
// Remove ag-grid nodes as necessary
const rowsToRemove = [];
this.gridApi.forEachNode(node => {
const {data} = node;
if (includes(symbolsRemoved, data.symbol)) {
rowsToRemove.push(data);
}
});
this.gridApi.updateRowData({remove: rowsToRemove});
// Subscribe to new ones that need to be added
const symbolsAdded = difference(nextSymbols, currentSymbols);
forEach(symbolsAdded, symbol => {
this.exchangeService.addSubscriber(this.updateSymbol, symbol);
});
// Remove ag-grid nodes as necessary
const nodesToRemove = [];
this.gridApi.forEachNode(node => {
const {data} = node;
if (includes(symbolsRemoved, data.symbol)) {
nodesToRemove.push(node);
}
});
this.gridApi.removeItems(nodesToRemove);
// Insert new ag-grid nodes as necessary
let rowData = map(symbolsAdded, symbol => this.exchangeService.getTicker(symbol));
this.gridApi.addItems(rowData);
this.gridApi.updateRowData({add: rowData});
// select the first symbol to show the chart
this.gridApi.getModel().getRow(0).setSelected(true);
@@ -139,35 +146,26 @@ export default class extends Component {
return;
}
const updatedNodes = [];
const updatedCols = [];
this.gridApi.forEachNode(node => {
const {data} = node;
if (data.symbol === symbol.symbol) {
for (const def of this.state.columnDefs) {
if (data[def.field] !== symbol[def.field]) {
updatedCols.push(def.field);
}
}
assign(data, symbol);
updatedNodes.push(node);
}
});
this.gridApi.refreshCells(updatedNodes, updatedCols);
};
this.gridApi.updateRowData({update: [symbol]});
}
render() {
return (
<div style={{height: 410, width: 800}}
className="ag-fresh">
className="ag-theme-balham">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
enableSorting="true"
defaultColDef={{
sortable: true
}}
rowSelection="single"
modules={[ClientSideRowModelModule]}
// callbacks
getRowNodeId={this.getRowNodeId}
// events
onGridReady={this.onGridReady}
onSelectionChanged={this.onSelectionChanged}>
@@ -175,4 +173,4 @@ export default class extends Component {
</div>
);
}
}
}

View File

@@ -1,7 +1,8 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import {AgGridReact} from "ag-grid-react";
import {AgGridReact} from "@ag-grid-community/react";
import {ClientSideRowModelModule} from "@ag-grid-enterprise/all-modules";
class TopMoversGrid extends Component {
constructor(props) {
@@ -17,24 +18,24 @@ class TopMoversGrid extends Component {
field: 'last',
headerName: 'Last',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClass: 'align-right'
},
{
field: 'net',
headerName: 'Net',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClass: 'align-right'
},
{
field: 'pct_net_change',
headerName: '% NC',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClass: 'align-right',
sort: 'desc',
cellFormatter(params) {
valueFormatter(params) {
return params.value.toFixed(2)
}
},
@@ -43,6 +44,8 @@ class TopMoversGrid extends Component {
// grid events
this.onGridReady = this.onGridReady.bind(this);
// grid callbacks
this.getRowNodeId = this.getRowNodeId.bind(this);
}
@@ -60,17 +63,21 @@ class TopMoversGrid extends Component {
render() {
return (
<div style={{height: 410, width: 400}}
className="ag-fresh">
className="ag-theme-balham">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.props.rowData}
enableSorting
enableFilter="false"
defaultColDef={{
sortable: true,
filter: false
}}
animateRows
deltaRowDataMode
getRowNodeId={this.getRowNodeId}
modules={[ClientSideRowModelModule]}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
@@ -82,7 +89,7 @@ class TopMoversGrid extends Component {
export default connect(
(state) => {
return {
rowData: state.fxTopMovers
rowData: state ? state.fxTopMovers : null
}
}
)(TopMoversGrid);
)(TopMoversGrid);

View File

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

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<script type="text/javascript" src="dist/react-trader.js" charset="utf-8"></script>
<script type="text/javascript" src="../dist/react-trader.js" charset="utf-8"></script>
<style>
html, body {

View File

@@ -5,12 +5,12 @@ import {render} from "react-dom";
import {Provider} from "react-redux";
import "ag-grid-root/dist/styles/ag-grid.css";
import "ag-grid-root/dist/styles/theme-fresh.css";
import StoreService from './services/StoreService';
import TraderDashboard from "./components/TraderDashboard.jsx";
import "@ag-grid-enterprise/all-modules/dist/styles/ag-grid.css";
import "@ag-grid-enterprise/all-modules/dist/styles/ag-theme-balham.css";
let store = StoreService.STORE;
document.addEventListener('DOMContentLoaded', () => {

View File

@@ -1,5 +1,4 @@
import concat from "lodash/concat";
import remove from "lodash/remove";
import uniq from "lodash/uniq";
import find from "lodash/find";
import sampleSize from "lodash/sampleSize";
@@ -26,7 +25,12 @@ export default class {
}
removeSubscriber(subscriber, symbol) {
remove(this.subscribers[symbol], subscriber);
let subscribers = this.subscribers[symbol];
subscribers.splice(subscribers.indexOf(subscriber), 1);
}
removeSubscribers() {
this.subscribers = {};
}
getTicker(symbol) {

View File

@@ -120,7 +120,7 @@ const FX_DELTA_HEADERS = [
field: 'last',
headerName: 'Last',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClass: 'align-right',
width: 100
},
@@ -128,7 +128,7 @@ const FX_DELTA_HEADERS = [
field: 'net',
headerName: 'Net',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClass: 'align-right',
width: 90
},
@@ -145,7 +145,7 @@ const FX_DELTA_HEADERS = [
headerName: symbol,
width: 67,
cellClass: 'align-right',
cellRenderer: 'animateShowChange',
cellRenderer: 'agAnimateShowChangeCellRenderer',
cellClassRules: {
'fx-positive': 'x > 0.8',
'fx-null': 'x === null',

View File

@@ -1,99 +0,0 @@
import React, {Component} from "react";
import "url-search-params-polyfill";
import DynamicComponentsExample from "./dynamicComponentExample/DynamicComponentsExample";
import RichGridExample from "./richGridExample/RichGridExample";
import RichComponentsExample from "./richComponentExample/RichComponentsExample";
import EditorComponentsExample from "./editorComponentExample/EditorComponentsExample";
import FloatingRowComponentExample from "./floatingRowExample/FloatingRowComponentExample";
import FullWidthComponentExample from "./fullWidthExample/FullWidthComponentExample";
import GroupedRowInnerRendererComponentExample from "./groupedRowInnerRendererExample/GroupedRowInnerRendererComponentExample";
import FilterComponentExample from "./filterComponentExample/FilterComponentExample";
import MasterDetailExample from "./masterDetailExample/MasterDetailExample";
import SimpleReduxExample from "./simpleReduxExample/SimpleReduxExample";
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) {
console.log(example);
this.setState({
example
})
}
render() {
let header = null;
if (!this.state.fromDocs) {
header = (
<ul className="nav nav-pills">
<li role="presentation" className={this.state.example === 'rich-grid' ? 'active' : null} onClick={() => this.setExample("rich-grid")}><a href="#">Rich Grid Example</a></li>
<li role="presentation" className={this.state.example === 'dynamic' ? 'active' : null} onClick={() => this.setExample("dynamic")}><a href="#">Dynamic React Component Example</a></li>
<li role="presentation" className={this.state.example === 'rich-dynamic' ? 'active' : null} onClick={() => this.setExample("rich-dynamic")}><a href="#">Dynamic React Components - Richer Example</a></li>
<li role="presentation" className={this.state.example === 'editor' ? 'active' : null} onClick={() => this.setExample("editor")}><a href="#">Cell Editor Component Example</a></li>
<li role="presentation" className={this.state.example === 'floating-row' ? 'active' : null} onClick={() => this.setExample("floating-row")}><a href="#">Floating 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 === 'master-detail' ? 'active' : null} onClick={() => this.setExample("master-detail")}><a href="#">Master Detail Example</a></li>
<li role="presentation" className={this.state.example === 'simple-redux' ? 'active' : null} onClick={() => this.setExample("simple-redux")}><a href="#">Simple Redux Example</a></li>
</ul>)
}
let example = null;
switch (this.state.example) {
case 'dynamic':
example = <DynamicComponentsExample/>;
break;
case 'rich-dynamic':
example = <RichComponentsExample/>;
break;
case 'editor':
example = <EditorComponentsExample/>;
break;
case 'floating-row':
example = <FloatingRowComponentExample/>;
break;
case 'full-width':
example = <FullWidthComponentExample/>;
break;
case 'group-row':
example = <GroupedRowInnerRendererComponentExample/>;
break;
case 'filter':
example = <FilterComponentExample/>;
break;
case 'master-detail':
example = <MasterDetailExample/>;
break;
case 'simple-redux':
example = <SimpleReduxExample/>;
break;
default:
example = <RichGridExample/>;
}
return (
<div>
{header}
{example}
</div>
)
}
}
export default App

View File

@@ -1,19 +0,0 @@
import React, {Component} from "react";
export default class ChildMessageRenderer extends Component {
constructor(props) {
super(props);
this.invokeParentMethod = this.invokeParentMethod.bind(this);
}
invokeParentMethod() {
this.props.context.componentParent.methodFromParent(`Row: ${this.props.node.rowIndex}, Col: ${this.props.colDef.headerName}`)
}
render() {
return (
<span><button style={{height: 20}} onClick={this.invokeParentMethod}>Invoke Parent</button></span>
);
}
};

View File

@@ -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>
);
}
};

View File

@@ -1,17 +0,0 @@
import React, {Component} from "react";
export default class CurrencyRenderer extends Component {
constructor(props) {
super(props);
}
formatValueToCurrency(currency, value) {
return `${currency}${value}`
}
render() {
return (
<span>{this.formatValueToCurrency('EUR', this.props.value)}</span>
);
}
};

View File

@@ -1,123 +0,0 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import SquareRenderer from "./SquareRenderer";
import CubeRenderer from "./CubeRenderer";
import ParamsRenderer from "./ParamsRenderer";
import CurrencyRenderer from "./CurrencyRenderer";
import ChildMessageRenderer from "./ChildMessageRenderer";
export default class DynamicComponentsExample extends Component {
constructor(props) {
super(props);
this.state = {
gridOptions: {
context: {
componentParent: this
}
},
rowData: this.createRowData(),
columnDefs: this.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
this.refreshRowData = this.refreshRowData.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
onCellValueChanged($event) {
this.gridApi.refreshCells([$event.node],["cube"]);
}
methodFromParent(cell) {
alert(`Parent Component Method from ${cell}!`);
}
createColumnDefs() {
return [
{headerName: "Row", field: "row", width: 100},
{
headerName: "Square",
field: "value",
cellRendererFramework: SquareRenderer,
editable:true,
colId: "square",
width: 100
},
{
headerName: "Cube",
field: "value",
cellRendererFramework: CubeRenderer,
colId: "cube",
width: 100
},
{
headerName: "Row Params",
field: "row",
cellRendererFramework: ParamsRenderer,
colId: "params",
width: 215
},
{
headerName: "Currency",
field: "currency",
cellRendererFramework: CurrencyRenderer,
colId: "params",
width: 135
},
{
headerName: "Child/Parent",
field: "value",
cellRendererFramework: ChildMessageRenderer,
colId: "params",
width: 120
}
];
}
refreshRowData() {
let rowData = this.createRowData();
this.gridApi.setRowData(rowData);
}
createRowData() {
let rowData = [];
for (let i = 0; i < 15; i++) {
rowData.push({
row: "Row " + i,
value: i,
currency: 1 + Number(Math.random()).toFixed(2)
});
}
return rowData;
}
render() {
return (
<div style={{height: 400, width: 945}}
className="ag-fresh">
<h1>Dynamic React Component Example</h1>
<button onClick={this.refreshRowData}>Refresh Data</button>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
gridOptions={this.state.gridOptions}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
);
}
};

View File

@@ -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>
);
}
};

View File

@@ -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>
);
}
};

View File

@@ -1,82 +0,0 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import MoodRenderer from "./MoodRenderer";
import MoodEditor from "./MoodEditor";
import NumericEditor from "./NumericEditor";
export default class EditorComponentsExample extends Component {
constructor(props) {
super(props);
this.state = {
rowData: this.createRowData(),
columnDefs: this.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
createColumnDefs() {
return [
{headerName: "Name", field: "name", width: 300},
{
headerName: "Mood",
field: "mood",
cellRendererFramework: MoodRenderer,
cellEditorFramework: MoodEditor,
editable: true,
width: 250
},
{
headerName: "Numeric",
field: "number",
cellEditorFramework: NumericEditor,
editable: true,
width: 250
}
];
}
createRowData() {
return [
{name: "Bob", mood: "Happy", number: 10},
{name: "Harry", mood: "Sad", number: 3},
{name: "Sally", mood: "Happy", number: 20},
{name: "Mary", mood: "Sad", number: 5},
{name: "John", mood: "Happy", number: 15},
{name: "Jack", mood: "Happy", number: 25},
{name: "Sue", mood: "Sad", number: 43},
{name: "Sean", mood: "Sad", number: 1335},
{name: "Niall", mood: "Happy", number: 2},
{name: "Alberto", mood: "Happy", number: 123},
{name: "Fred", mood: "Sad", number: 532},
{name: "Jenny", mood: "Happy", number: 34},
{name: "Larry", mood: "Happy", number: 13},
];
}
render() {
return (
<div style={{height: 400, width: 945}}
className="ag-fresh">
<h1>Cell Editor Component Example</h1>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
);
}
};

View File

@@ -1,107 +0,0 @@
import React, {Component} from "react";
import ReactDOM from "react-dom";
export default class MoodEditor extends Component {
constructor(props) {
super(props);
this.onHappyClick = this.onHappyClick.bind(this);
this.onSadClick = this.onSadClick.bind(this);
this.state = {
happy: false
}
}
componentWillMount() {
this.setHappy(this.props.value === "Happy");
}
componentDidMount() {
this.focus();
}
componentDidUpdate() {
this.focus();
}
focus() {
setTimeout(() => {
let container = ReactDOM.findDOMNode(this.refs.container);
if (container) {
container.focus();
}
})
}
getValue() {
return this.state.happy ? "Happy" : "Sad";
}
isPopup() {
return true;
}
setHappy(happy) {
this.setState({
happy
});
}
onHappyClick() {
this.setState({
happy: true
},
() => this.props.api.stopEditing()
);
}
onSadClick() {
this.setState({
happy: false
},
() => this.props.api.stopEditing()
);
}
toggleMood() {
this.setHappy(!this.state.happy);
}
render() {
let mood = {
borderRadius: 15,
border: "1px solid grey",
background: "#e6e6e6",
padding: 15,
textAlign: "center",
display: "inline-block",
// outline: "none"
};
let unselected = {
paddingLleft: 10,
paddingRight: 10,
border: "1px solid transparent",
padding: 4
};
let selected = {
paddingLeft: 10,
paddingRight: 10,
border: "1px solid lightgreen",
padding: 4
};
let happyStyle = this.state.value === 'Happy' ? selected : unselected;
let sadStyle = this.state.value !== 'Happy' ? selected : unselected;
return (
<div ref="container"
style={mood}>
<img src="images/smiley.png" onClick={this.onHappyClick} style={happyStyle}/>
<img src="images/smiley-sad.png" onClick={this.onSadClick} style={sadStyle}/>
</div>
);
}
}

View File

@@ -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}/>
);
}
}

View File

@@ -1,83 +0,0 @@
import React, {Component} from "react";
import ReactDOM from "react-dom";
export default class MoodEditor extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value
};
this.cancelBeforeStart = this.props.charPress && ('1234567890'.indexOf(this.props.charPress) < 0);
this.onKeyDown = this.onKeyDown.bind(this);
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
this.focus();
}
componentDidUpdate() {
this.focus();
}
focus() {
setTimeout(() => {
let container = ReactDOM.findDOMNode(this.refs.input);
if (container) {
container.focus();
}
})
}
getValue() {
return this.state.value;
}
isCancelBeforeStart() {
return this.cancelBeforeStart;
}
// will reject the number if it greater than 1,000,000
// not very practical, but demonstrates the method.
isCancelAfterEnd() {
return this.state.value > 1000000;
};
onKeyDown(event) {
if (!this.isKeyPressedNumeric(event)) {
if (event.preventDefault) event.preventDefault();
}
}
handleChange(event) {
this.setState({value: event.target.value});
}
getCharCodeFromEvent(event) {
event = event || window.event;
return (typeof event.which === "undefined") ? event.keyCode : event.which;
}
isCharNumeric(charStr) {
return !!/\d/.test(charStr);
}
isKeyPressedNumeric(event) {
const charCode = this.getCharCodeFromEvent(event);
const charStr = event.key ? event.key : String.fromCharCode(charCode);
return this.isCharNumeric(charStr);
}
render() {
return (
<input ref="input"
value={this.state.value}
onKeyDown={this.onKeyDown}
onChange={this.handleChange}
/>
);
}
}

View File

@@ -1,87 +0,0 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import "ag-grid-enterprise";
import PartialMatchFilter from "./PartialMatchFilter";
export default class FilterComponentExample extends Component {
constructor(props) {
super(props);
this.state = {
gridOptions: {},
rowData: this.createRowData(),
columnDefs: this.createColumnDefs(),
};
this.onGridReady = this.onGridReady.bind(this);
this.onClicked = this.onClicked.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
onClicked() {
this.gridApi.getFilterInstance("name").getFrameworkComponentInstance().componentMethod("Hello World!");
}
createColumnDefs() {
return [
{headerName: "Row", field: "row", width: 400},
{
headerName: "Filter Component",
field: "name",
filterFramework: PartialMatchFilter,
width: 400
}
];
}
createRowData() {
return [
{"row": "Row 1", "name": "Michael Phelps"},
{"row": "Row 2", "name": "Natalie Coughlin"},
{"row": "Row 3", "name": "Aleksey Nemov"},
{"row": "Row 4", "name": "Alicia Coutts"},
{"row": "Row 5", "name": "Missy Franklin"},
{"row": "Row 6", "name": "Ryan Lochte"},
{"row": "Row 7", "name": "Allison Schmitt"},
{"row": "Row 8", "name": "Natalie Coughlin"},
{"row": "Row 9", "name": "Ian Thorpe"},
{"row": "Row 10", "name": "Bob Mill"},
{"row": "Row 11", "name": "Willy Walsh"},
{"row": "Row 12", "name": "Sarah McCoy"},
{"row": "Row 13", "name": "Jane Jack"},
{"row": "Row 14", "name": "Tina Wills"}
];
}
render() {
return (
<div style={{height: 400, width: 945}}
className="ag-fresh">
<h1>Filter Component Example</h1>
<button style={{marginBottom: 10}} onClick={this.onClicked}>Filter Instance Method</button>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
enableFilter
suppressMenuColumnPanel // ag-enterprise only
suppressMenuMainPanel // ag-enterprise only
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
);
}
};

View File

@@ -1,70 +0,0 @@
import React, {Component} from "react";
import ReactDOM from "react-dom";
export default class PartialMatchFilter extends Component {
constructor(props) {
super(props);
this.state = {
text: ''
}
this.valueGetter = this.props.valueGetter;
this.onChange = this.onChange.bind(this);
}
isFilterActive() {
return this.state.text !== null && this.state.text !== undefined && this.state.text !== '';
}
doesFilterPass(params) {
return this.state.text.toLowerCase()
.split(" ")
.every((filterWord) => {
return this.valueGetter(params.node).toString().toLowerCase().indexOf(filterWord) >= 0;
});
}
getModel() {
return {value: this.state.text};
}
setModel(model) {
this.state.text = model ? model.value : '';
}
afterGuiAttached(params) {
this.focus();
}
focus() {
setTimeout(() => {
let container = ReactDOM.findDOMNode(this.refs.input);
if (container) {
container.focus();
}
})
}
componentMethod(message) {
alert(`Alert from PartialMatchFilterComponent ${message}`);
}
onChange(event) {
let newValue = event.target.value;
if (this.state.text !== newValue) {
this.setState({
text: newValue
}, () => {
this.props.filterChangedCallback();
});
}
}
render() {
return (
<span>Filter: <input style={{height: "20px"}} ref="input" value={this.state.text} onChange={this.onChange}/></span>
);
}
};

View File

@@ -1,85 +0,0 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import StyledRenderer from "./StyledRenderer";
export default class FloatingRowComponentExample extends Component {
constructor(props) {
super(props);
this.state = {
gridOptions: {},
rowData: this.createRowData(),
columnDefs: this.createColumnDefs(),
topFloatingRowData: [{row: "Top Row", number: "Top Number"}],
bottomFloatingRowData: [{row: "Bottom Row", number: "Bottom Number"}]
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
createColumnDefs() {
return [
{
headerName: "Row",
field: "row",
width: 400,
floatingCellRendererFramework: StyledRenderer,
floatingCellRendererParams: {
style: {'fontWeight': 'bold'}
}
},
{
headerName: "Number",
field: "number",
width: 399,
floatingCellRendererFramework: StyledRenderer,
floatingCellRendererParams: {
style: {'fontStyle': 'italic'}
}
},
];
}
createRowData() {
let rowData = [];
for (let i = 0; i < 15; i++) {
rowData.push({
row: "Row " + i,
number: Math.round(Math.random() * 100)
});
}
return rowData;
}
render() {
return (
<div style={{height: 400, width: 945}}
className="ag-fresh">
<h1>Floating Row Renderer Example</h1>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
floatingTopRowData={this.state.topFloatingRowData}
floatingBottomRowData={this.state.bottomFloatingRowData}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
);
}
};

View File

@@ -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: this.createRowData(),
columnDefs: this.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);
}
createColumnDefs() {
return [
{
headerName: "Name",
field: "name",
width: 400
},
{
headerName: "Age",
field: "age",
width: 399
},
];
}
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: 945}}
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>
);
}
};

Some files were not shown because too many files have changed in this diff Show More