From 3390411e8a572810b1cb9f90e8da8dace22f2d77 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 23 Jan 2017 12:30:15 +0000 Subject: [PATCH] React date component, polishing the UI and adding documentation --- src-standard/MyReactDateComponent.jsx | 183 ++++++++++++++++++++------ src-standard/myApp.jsx | 9 ++ 2 files changed, 149 insertions(+), 43 deletions(-) diff --git a/src-standard/MyReactDateComponent.jsx b/src-standard/MyReactDateComponent.jsx index 495192d..d298abc 100644 --- a/src-standard/MyReactDateComponent.jsx +++ b/src-standard/MyReactDateComponent.jsx @@ -1,64 +1,161 @@ import React from 'react'; -import RefData from './RefData'; -// Date Component to be used in the date filter +// 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 { constructor(props) { super(props); - // the entire ag-Grid properties are passed as one single object inside the params + //The state of this component is represented of: + // The current date it holds, null by default, null if the date typed by the user is not valid or fields are blank + // The current values that the user types in the input boxes, by default '' + + //The textBoxes state is necessary since it can be set from ag-Grid. This can be seen in this example through + // the usage of the button DOB equals to 01/01/2000 in the example page. this.state = { - agProps: props - }; - } - - - onDateChanged () { - if (this.refs.dd.value === '' || this.refs.mm.value === '' || this.refs.yyyy.value === '') { - return; - } - - try { - var day = Number(this.refs.dd.value); - var month = Number(this.refs.mm.value); - var year = Number(this.refs.yyyy.value); - - var date = new Date(year, month - 1, day); - if (date){ - this.setState({ - date:date - }, this.notifyAgGrid.bind(this)) + date: null, + textBoxes: { + dd: '', + mm: '', + yyyy: '' } - } catch (e){ - console.info("ignoring invalid date") } } - notifyAgGrid (){ - this.props.onDateChanged(); - } - - getDate (){ - return this.state.date; - } - - setDate (date){ - this.setState({ - date:date - }) - } - render() { + //Inlining styles to make simpler the component + let filterStyle = { + margin:'2px' + }; + let ddStyle = { + width: '30px' + }; + let mmStyle = { + width: '30px' + }; + let yyyyStyle = { + width: '60px' + }; + let resetStyle = { + padding: '2px', + backgroundColor: 'red', + borderRadius: '3px', + fontSize: '10px', + marginRight: '5px', + color: 'white' + }; + return ( -
- - - +
+ x + / + / +
); } + //********************************************************************************* + // METHODS REQUIRED BY AG-GRID + //********************************************************************************* + 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){ + //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() + } + }) + } + + //********************************************************************************* + // LINKS THE INTERNAL STATE AND AG-GRID + //********************************************************************************* + + updateAndNotifyAgGrid (date, textBoxes){ + this.setState ({ + date: date, + 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 + this.props.onDateChanged + ); + } + + + //********************************************************************************* + // LINKING THE UI, THE STATE AND AG-GRID + //********************************************************************************* + + resetDate (){ + let date = null; + let textBoxes = { + dd : '', + mm : '', + yyyy : '', + }; + + this.updateAndNotifyAgGrid(date, textBoxes) + } + + 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, + }; + + this.updateAndNotifyAgGrid(date, textBoxes) + } + + //********************************************************************************* + // INTERNAL LOGIC + //********************************************************************************* + + 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; + } + + let day = Number(dd); + let month = Number(mm); + let year = Number(yyyy); + + let date = new Date(year, month - 1, day); + + //If the date is not valid + if (isNaN(date.getTime())){ + return null; + } + + //Given that new Date takes any garbage in, it is possible for the user to specify a new Date + //like this (-1, 35, 1) and it will return a valid javascript date. In this example, it will + //return Sat Dec 01 1 00:00:00 GMT+0000 (GMT) - Go figure... + //To ensure that we are not letting non sensical dates to go through we check that the resultant + //javascript date parts (month, year and day) match the given date fields provided as parameters. + //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){ + return null; + } + + return date; + } } // the grid will always pass in one props called 'params', diff --git a/src-standard/myApp.jsx b/src-standard/myApp.jsx index e7fd38e..acdc39f 100644 --- a/src-standard/myApp.jsx +++ b/src-standard/myApp.jsx @@ -101,6 +101,14 @@ export default class MyApp extends React.Component { componentInstance.helloFromSkillsFilter(); } + dobFilter () { + let dateFilterComponent = this.gridOptions.api.getFilterInstance('dob'); + dateFilterComponent.setFilterType('equals'); + dateFilterComponent.setDateFrom('2000-01-01'); + this.gridOptions.api.onFilterChanged(); + + } + render() { var gridTemplate; var bottomHeaderTemplate; @@ -152,6 +160,7 @@ export default class MyApp extends React.Component { Filter API: +