1+ import React from "react" ;
2+ import * as PropTypes from "prop-types" ;
3+
4+ // Date Component to be used in the date filter.
5+ // This is a very simple example of how a React component can be plugged as a DateComponentFramework
6+ // as you can see, the only requirement is that the React component implements the required methods
7+ // getDate and setDate and that it calls back into props.onDateChanged every time that the date changes.
8+ export default class DateComponent extends React . Component {
9+
10+ constructor ( props ) {
11+ super ( props ) ;
12+ //The state of this component is represented of:
13+ // The current date it holds, null by default, null if the date typed by the user is not valid or fields are blank
14+ // The current values that the user types in the input boxes, by default ''
15+
16+ //The textBoxes state is necessary since it can be set from ag-Grid. This can be seen in this example through
17+ // the usage of the button DOB equals to 01/01/2000 in the example page.
18+ this . state = {
19+ date : null ,
20+ textBoxes : {
21+ dd : '' ,
22+ mm : '' ,
23+ yyyy : ''
24+ }
25+ }
26+ }
27+
28+ render ( ) {
29+ //Inlining styles to make simpler the component
30+ let filterStyle = {
31+ margin : '2px'
32+ } ;
33+ let ddStyle = {
34+ width : '30px'
35+ } ;
36+ let mmStyle = {
37+ width : '30px'
38+ } ;
39+ let yyyyStyle = {
40+ width : '40px'
41+ } ;
42+ let resetStyle = {
43+ padding : '2px' ,
44+ backgroundColor : 'red' ,
45+ borderRadius : '3px' ,
46+ fontSize : '10px' ,
47+ marginRight : '5px' ,
48+ color : 'white'
49+ } ;
50+
51+ return (
52+ < div style = { filterStyle } >
53+ < span style = { resetStyle } onClick = { this . resetDate . bind ( this ) } > x</ span >
54+ < input onInput = { this . onDateChanged . bind ( this ) } ref = "dd" placeholder = "dd" style = { ddStyle }
55+ value = { this . state . textBoxes . dd } maxLength = "2" /> /
56+ < input onInput = { this . onDateChanged . bind ( this ) } ref = "mm" placeholder = "mm" style = { mmStyle }
57+ value = { this . state . textBoxes . mm } maxLength = "2" /> /
58+ < input onInput = { this . onDateChanged . bind ( this ) } ref = "yyyy" placeholder = "yyyy" style = { yyyyStyle }
59+ value = { this . state . textBoxes . yyyy } maxLength = "4" />
60+ </ div >
61+ ) ;
62+ }
63+
64+ //*********************************************************************************
65+ // METHODS REQUIRED BY AG-GRID
66+ //*********************************************************************************
67+
68+ getDate ( ) {
69+ //ag-grid will call us here when in need to check what the current date value is hold by this
70+ //component.
71+ return this . state . date ;
72+ }
73+
74+ setDate ( date ) {
75+ //ag-grid will call us here when it needs this component to update the date that it holds.
76+ this . setState ( {
77+ date,
78+ textBoxes : {
79+ dd : date ? date . getDate ( ) : '' ,
80+ mm : date ? date . getMonth ( ) + 1 : '' ,
81+ yyyy : date ? date . getFullYear ( ) : ''
82+ }
83+ } )
84+ }
85+
86+ //*********************************************************************************
87+ // LINKS THE INTERNAL STATE AND AG-GRID
88+ //*********************************************************************************
89+
90+ updateAndNotifyAgGrid ( date , textBoxes ) {
91+ this . setState ( {
92+ date : date ,
93+ textBoxes : textBoxes
94+ } ,
95+ //Callback after the state is set. This is where we tell ag-grid that the date has changed so
96+ //it will proceed with the filtering and we can then expect ag-Grid to call us back to getDate
97+ this . props . onDateChanged
98+ ) ;
99+ }
100+
101+
102+ //*********************************************************************************
103+ // LINKING THE UI, THE STATE AND AG-GRID
104+ //*********************************************************************************
105+
106+ resetDate ( ) {
107+ let date = null ;
108+ let textBoxes = {
109+ dd : '' ,
110+ mm : '' ,
111+ yyyy : '' ,
112+ } ;
113+
114+ this . updateAndNotifyAgGrid ( date , textBoxes )
115+ }
116+
117+ onDateChanged ( ) {
118+ let date = this . parseDate ( this . refs . dd . value , this . refs . mm . value , this . refs . yyyy . value ) ;
119+ let textBoxes = {
120+ dd : this . refs . dd . value ,
121+ mm : this . refs . mm . value ,
122+ yyyy : this . refs . yyyy . value ,
123+ } ;
124+
125+ this . updateAndNotifyAgGrid ( date , textBoxes )
126+ }
127+
128+ //*********************************************************************************
129+ // INTERNAL LOGIC
130+ //*********************************************************************************
131+
132+ parseDate ( dd , mm , yyyy ) {
133+ //If any of the three input date fields are empty, stop and return null
134+ if ( dd . trim ( ) === '' || mm . trim ( ) === '' || yyyy . trim ( ) === '' ) {
135+ return null ;
136+ }
137+
138+ let day = Number ( dd ) ;
139+ let month = Number ( mm ) ;
140+ let year = Number ( yyyy ) ;
141+
142+ let date = new Date ( year , month - 1 , day ) ;
143+
144+ //If the date is not valid
145+ if ( isNaN ( date . getTime ( ) ) ) {
146+ return null ;
147+ }
148+
149+ //Given that new Date takes any garbage in, it is possible for the user to specify a new Date
150+ //like this (-1, 35, 1) and it will return a valid javascript date. In this example, it will
151+ //return Sat Dec 01 1 00:00:00 GMT+0000 (GMT) - Go figure...
152+ //To ensure that we are not letting non sensical dates to go through we check that the resultant
153+ //javascript date parts (month, year and day) match the given date fields provided as parameters.
154+ //If the javascript date parts don't match the provided fields, we assume that the input is non
155+ //sensical... ie: Day=-1 or month=14, if this is the case, we return null
156+ //This also protects us from non sensical dates like dd=31, mm=2 of any year
157+ if ( date . getDate ( ) != day || date . getMonth ( ) + 1 != month || date . getFullYear ( ) != year ) {
158+ return null ;
159+ }
160+
161+ return date ;
162+ }
163+ }
164+
165+ // the grid will always pass in one props called 'params',
166+ // which is the grid passing you the params for the cellRenderer.
167+ // this piece is optional. the grid will always pass the 'params'
168+ // props, so little need for adding this validation meta-data.
169+ DateComponent . propTypes = {
170+ params : PropTypes . object
171+ } ;
0 commit comments