AG-1053 Tidy react examples, make more idiomatic

This commit is contained in:
Sean Landsman
2017-11-08 14:45:28 +00:00
parent b030235bbc
commit 983b5974cf
149 changed files with 339 additions and 8856 deletions

View File

@@ -0,0 +1,132 @@
import React, {Component} from "react";
import {AgGridReact} from "ag-grid-react";
import MoodRenderer from "./MoodRenderer";
import MoodEditor from "./MoodEditor";
import NumericEditor from "./NumericEditor";
export default class EditorComponentsExample extends Component {
constructor(props) {
super(props);
this.state = {
rowData: EditorComponentsExample.createRowData(),
columnDefs: EditorComponentsExample.createColumnDefs()
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
static createColumnDefs() {
return [
{
headerName: "Name",
field: "name",
width: 300,
editable: true,
cellEditor: 'richSelect',
cellEditorParams: {
values: [
"Bob",
"Harry",
"Sally",
"Mary",
"John",
"Jack",
"Sue",
"Sean",
"Niall",
"Albert",
"Fred",
"Jenny",
"Larry"
]
}
},
{
headerName: "Mood",
field: "mood",
cellRendererFramework: MoodRenderer,
cellEditorFramework: MoodEditor,
editable: true,
width: 250
},
{
headerName: "Numeric",
field: "number",
cellEditorFramework: NumericEditor,
editable: true,
width: 250
}
];
}
static createRowData() {
return [
{name: "Bob", mood: "Happy", number: 10},
{name: "Harry", mood: "Sad", number: 3},
{name: "Sally", mood: "Happy", number: 20},
{name: "Mary", mood: "Sad", number: 5},
{name: "John", mood: "Happy", number: 15},
{name: "Jack", mood: "Happy", number: 25},
{name: "Sue", mood: "Sad", number: 43},
{name: "Sean", mood: "Sad", number: 1335},
{name: "Niall", mood: "Happy", number: 2},
{name: "Alberto", mood: "Happy", number: 123},
{name: "Fred", mood: "Sad", number: 532},
{name: "Jenny", mood: "Happy", number: 34},
{name: "Larry", mood: "Happy", number: 13},
];
}
render() {
return (
<div style={{height: 370, width: 900}}
className="ag-fresh">
<h1>Cell Editor Component Example</h1>
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
rowData={this.state.rowData}
// events
onGridReady={this.onGridReady}>
</AgGridReact>
<div className="row">
<div className="col-sm-12"><h1>Cell Editor Component Example</h1></div>
</div>
<div className="row">
<div className="col-sm-12">
<h5>This example demonstrates React Editor Components within ag-Grid, as well as an example using the built in Rich Select editor.</h5>
<p><span style={{fontWeight: "bold"}}>Name</span>: Utilises the built in <code>RichSelect</code> editor</p>
<p><span style={{fontWeight: "bold"}}>Mood</span>: A Custom React Editor demonstrating popup functionality, with full keyboard control.</p>
<p><span style={{fontWeight: "bold"}}>Numeric</span>: A Custom React Editor demonstrating pre & post validation. Only numeric characters are allowed,
and numbers greater than 1000000 will be rejected.</p>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<h4 className="card-title">React Functionality</h4>
<p className="card-text">Utilise React Components within ag-Grid</p>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editing/?framework=react" className="btn btn-primary">Cell Editing</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react" className="btn btn-primary">Editor Components</a>
<a target="_blank" href="https://www.ag-grid.com/best-react-data-grid/?framework=react" className="btn btn-primary">React with ag-Grid</a>
<a target="_blank" href="https://www.ag-grid.com/javascript-grid-cell-editor/?framework=react#reactCellEditing" className="btn btn-primary">React Editor Components</a>
</div>
</div>
</div>
</div>
</div>
);
}
};

View File

@@ -0,0 +1,120 @@
import React, {Component} from "react";
import ReactDOM from "react-dom";
export default class MoodEditor extends Component {
constructor(props) {
super(props);
this.onHappyClick = this.onHappyClick.bind(this);
this.onSadClick = this.onSadClick.bind(this);
this.state = {
happy: false
}
}
componentWillMount() {
this.setHappy(this.props.value === "Happy");
}
componentDidMount() {
this.refs.container.addEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
this.focus();
}
componentWillUnmount() {
this.refs.container.removeEventListener('keydown', this.checkAndToggleMoodIfLeftRight);
}
checkAndToggleMoodIfLeftRight = (event) => {
if ([37, 39].indexOf(event.keyCode) > -1) { // left and right
this.toggleMood();
event.stopPropagation();
}
}
componentDidUpdate() {
this.focus();
}
focus() {
setTimeout(() => {
let container = ReactDOM.findDOMNode(this.refs.container);
if (container) {
container.focus();
}
})
}
getValue() {
return this.state.happy ? "Happy" : "Sad";
}
isPopup() {
return true;
}
setHappy(happy) {
this.setState({
happy
});
}
onHappyClick() {
this.setState({
happy: true
},
() => this.props.api.stopEditing()
);
}
onSadClick() {
this.setState({
happy: false
},
() => this.props.api.stopEditing()
);
}
toggleMood() {
this.setHappy(!this.state.happy);
}
render() {
let mood = {
borderRadius: 15,
border: "1px solid grey",
background: "#e6e6e6",
padding: 15,
textAlign: "center",
display: "inline-block"
};
let unselected = {
paddingLeft: 10,
paddingRight: 10,
border: "1px solid transparent",
padding: 4
};
let selected = {
paddingLeft: 10,
paddingRight: 10,
border: "1px solid lightgreen",
padding: 4
};
let happyStyle = this.state.happy ? selected : unselected;
let sadStyle = !this.state.happy ? selected : unselected;
return (
<div ref="container"
style={mood}
tabIndex={1} // important - without this the keypresses wont be caught
>
<img src="images/smiley.png" onClick={this.onHappyClick} style={happyStyle}/>
<img src="images/smiley-sad.png" onClick={this.onSadClick} style={sadStyle}/>
</div>
);
}
}

View File

@@ -0,0 +1,27 @@
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

@@ -0,0 +1,102 @@
import React, {Component} from "react";
export default class NumericEditor extends Component {
constructor(props) {
super(props);
// if the character pressed to start editing isn't numeric we set this flag, which will mean editing wont be initiated
this.cancelBeforeStart = this.props.charPress && ('1234567890'.indexOf(this.props.charPress) < 0);
let value = this.props.value;
if (!this.cancelBeforeStart && this.props.charPress) {
value = value + this.props.charPress;
}
this.state = {
value
};
}
componentDidMount() {
this.refs.input.addEventListener('keydown', this.onKeyDown);
this.focus();
}
componentWillUnmount() {
this.refs.input.removeEventListener('keydown', this.onKeyDown);
}
// componentDidUpdate() {
// this.focus();
// }
focus() {
if (!this.cancelBeforeStart) {
setTimeout(() => {
this.refs.input.focus();
this.refs.input.setSelectionRange(this.refs.input.value.length, this.refs.input.value.length);
})
}
}
getValue() {
return this.state.value;
}
isCancelBeforeStart() {
return this.cancelBeforeStart;
}
// will reject the number if it greater than 1,000,000
// not very practical, but demonstrates the method.
isCancelAfterEnd() {
return this.state.value > 1000000;
};
handleChange = (event) => {
this.setState({value: event.target.value});
};
onKeyDown = (event) => {
// allow back and forth navigation, as well as editing
if (NumericEditor.isAllowableKeypress(event)) {
event.stopPropagation();
return;
}
// if not a numeral, then reject the keypress
if (!NumericEditor.isKeyPressedNumeric(event)) {
if (event.preventDefault) event.preventDefault();
}
};
static isAllowableKeypress(event) {
// left, right, backspace & delete
return [37, 39, 46, 8].indexOf(event.keyCode) > -1;
}
static getCharCodeFromEvent(event) {
event = event || window.event;
return (typeof event.which === "undefined") ? event.keyCode : event.which;
}
static isCharNumeric(charStr) {
return !!/\d/.test(charStr);
}
static isKeyPressedNumeric(event) {
const charCode = NumericEditor.getCharCodeFromEvent(event);
const charStr = event.key ? event.key : String.fromCharCode(charCode);
return this.isCharNumeric(charStr);
}
render() {
return (
<input ref="input"
value={this.state.value}
onChange={this.handleChange}
style={{width: "100%",padding:0,margin:-1}}
/>
);
}
}