AG-538 Upgrade to React 15x

AG-539 React rich grid example - fix bugs
This commit is contained in:
Sean Landsman
2017-06-13 18:15:05 +01:00
parent a4dbbf529d
commit 675cbe497c
13 changed files with 98 additions and 77 deletions

View File

@@ -42,6 +42,7 @@
"babel-preset-react": "6.24.x",
"babel-preset-stage-0": "6.24.x",
"babel-preset-stage-1": "6.24.x",
"prop-types": "15.5.x",
"css-loader": "0.23.x",
"mkdirp": "0.5.1",
"ncp": "2.0.0",

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,4 +1,5 @@
import React, {Component} from "react";
import * as PropTypes from 'prop-types';
export default class HorizontalBarComponent extends Component {
@@ -38,5 +39,5 @@ export default class HorizontalBarComponent extends Component {
}
HorizontalBarComponent.propTypes = {
params: React.PropTypes.object
params: PropTypes.object
};

View File

@@ -30,7 +30,6 @@ class App extends Component {
}
setExample(example) {
console.log(example);
this.setState({
example
})

View File

@@ -4,7 +4,7 @@ import ProficiencyCellRenderer from './ProficiencyCellRenderer.jsx';
import RefData from './RefData';
import SkillsFilter from './SkillsFilter.jsx';
import ProficiencyFilter from './ProficiencyFilter.jsx';
import MyReactHeaderGroupComponent from './MyReactHeaderGroupComponent.jsx';
import HeaderGroupComponent from './HeaderGroupComponent.jsx';
export default class ColDefFactory {
@@ -15,7 +15,7 @@ export default class ColDefFactory {
suppressMenu: true, pinned: true},
{
headerName: 'Employee',
headerGroupComponentFramework: MyReactHeaderGroupComponent,
headerGroupComponentFramework: HeaderGroupComponent,
children: [
{
headerName: "Name", field: "name", enableRowGroup: true, enablePivot: true,

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'
@@ -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 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"/>
</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,14 +1,18 @@
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();
}
@@ -36,6 +40,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,5 +1,6 @@
import React from 'react';
import RefData from './RefData';
import * as PropTypes from 'prop-types';
var KEY_BACKSPACE = 8;
var KEY_DELETE = 46;
@@ -113,5 +114,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

@@ -32,11 +32,9 @@ export default class ProficiencyFilter extends React.Component {
};
onButtonPressed(name) {
console.log(name);
var newState = {selected: name};
// set the state, and once it is done, then call filterChangedCallback
this.setState(newState, this.props.filterChangedCallback);
console.log(name);
}
render() {

View File

@@ -2,8 +2,8 @@ import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import RowDataFactory from "./RowDataFactory";
import ColDefFactory from "./ColDefFactory.jsx";
import MyReactDateComponent from "./MyReactDateComponent.jsx";
import MyReactHeaderComponent from "./MyReactHeaderComponent.jsx";
import DateComponent from "./DateComponent.jsx";
import SortableHeaderComponent from "./SortableHeaderComponent";
import "./RichGridExample.css";
@@ -41,13 +41,13 @@ export default class RichGridExample extends Component {
// what you want!
this.gridOptions = {
//We register the react date component that ag-grid will use to render
dateComponentFramework: MyReactDateComponent,
dateComponentFramework: DateComponent,
// this is how you listen for events using gridOptions
onModelUpdated: function () {
console.log('event onModelUpdated received');
},
defaultColDef: {
headerComponentFramework: MyReactHeaderComponent,
headerComponentFramework: SortableHeaderComponent,
headerComponentParams: {
menuIcon: 'fa-bars'
}
@@ -101,15 +101,15 @@ export default class RichGridExample extends Component {
}
onRefreshData() {
var newRowData = new RowDataFactory().createRowData();
let newRowData = new RowDataFactory().createRowData();
this.setState({
rowData: newRowData
});
}
invokeSkillsFilterMethod() {
var skillsFilter = this.api.getFilterInstance('skills');
var componentInstance = skillsFilter.getFrameworkComponentInstance();
let skillsFilter = this.api.getFilterInstance('skills');
let componentInstance = skillsFilter.getFrameworkComponentInstance();
componentInstance.helloFromSkillsFilter();
}
@@ -117,14 +117,19 @@ export default class RichGridExample extends Component {
let dateFilterComponent = this.gridOptions.api.getFilterInstance('dob');
dateFilterComponent.setFilterType('equals');
dateFilterComponent.setDateFrom('2000-01-01');
this.gridOptions.api.onFilterChanged();
// 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.gridOptions.api.onFilterChanged();
},0)
}
render() {
var gridTemplate;
var bottomHeaderTemplate;
var topHeaderTemplate;
let gridTemplate;
let bottomHeaderTemplate;
let topHeaderTemplate;
topHeaderTemplate = (
<div>

View File

@@ -1,4 +1,5 @@
import React from 'react';
import * as PropTypes from 'prop-types';
import RefData from './RefData';
export default class SkillsCellRenderer extends React.Component {
@@ -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,11 +31,11 @@ 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
});
}

View File

@@ -1,7 +1,8 @@
import React from 'react';
import React from "react";
import * as PropTypes from "prop-types";
// Header component to be used as default for all the columns.
export default class MyReactHeaderComponent extends React.Component {
export default class SortableHeaderComponent extends React.Component {
constructor(props) {
super(props);
@@ -11,27 +12,32 @@ export default class MyReactHeaderComponent extends React.Component {
//The state of this component contains the current sort state of this column
//The possible values are: 'asc', 'desc' and ''
this.state = {
sorted: ''
sorted: ''
}
}
render() {
let sortElements = [];
if (this.props.enableSorting){
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 className={downArrowClass} onClick={this.onSortRequested.bind(this, 'desc')}><i className="fa fa-long-arrow-down"/></div>)
sortElements.push(<div className={upArrowClass} onClick={this.onSortRequested.bind(this, 'asc')}><i className="fa fa-long-arrow-up"/></div>)
sortElements.push(<div className={removeArrowClass} onClick={this.onSortRequested.bind(this, '')}><i className="fa fa-times"/></div>)
sortElements.push(<div key={`up${this.props.displayName}`} className={downArrowClass} onClick={this.onSortRequested.bind(this, 'desc')}><i
className="fa fa-long-arrow-down"/></div>)
sortElements.push(<div key={`down${this.props.displayName}`} className={upArrowClass} onClick={this.onSortRequested.bind(this, 'asc')}><i
className="fa fa-long-arrow-up"/></div>)
sortElements.push(<div key={`minus${this.props.displayName}`} className={removeArrowClass} onClick={this.onSortRequested.bind(this, '')}><i
className="fa fa-times"/></div>)
}
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>
if (this.props.enableMenu) {
menuButton =
<div ref="menuButton" className="customHeaderMenuButton" onClick={this.onMenuClick.bind(this)}><i
className={"fa " + this.props.menuIcon}/></div>
}
return <div>
@@ -41,16 +47,16 @@ export default class MyReactHeaderComponent extends React.Component {
</div>
}
onSortRequested (order, event) {
this.props.setSort (order, event.shiftKey);
onSortRequested(order, event) {
this.props.setSort(order, event.shiftKey);
};
onSortChanged (){
if (this.props.column.isSortAscending()){
onSortChanged() {
if (this.props.column.isSortAscending()) {
this.setState({
sorted: 'asc'
})
} else if (this.props.column.isSortDescending()){
} else if (this.props.column.isSortDescending()) {
this.setState({
sorted: 'desc'
})
@@ -61,8 +67,8 @@ export default class MyReactHeaderComponent extends React.Component {
}
};
onMenuClick (){
this.props.showColumnMenu (this.refs.menuButton);
onMenuClick() {
this.props.showColumnMenu(this.refs.menuButton);
};
}
@@ -71,6 +77,6 @@ export default class MyReactHeaderComponent 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.
MyReactHeaderComponent.propTypes = {
params: React.PropTypes.object
SortableHeaderComponent.propTypes = {
params: PropTypes.object
};