Skip to content

Commit

Permalink
DatePicker (controlled): set state only if different; warn on setDate().
Browse files Browse the repository at this point in the history
  • Loading branch information
marnusw committed Jul 23, 2015
1 parent a0d5151 commit 1b190d0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
52 changes: 23 additions & 29 deletions src/date-picker/date-picker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ let DateTime = require('../utils/date-time');
let DatePickerDialog = require('./date-picker-dialog');
let TextField = require('../text-field');

/**
* Check if a value is a valid Date instance.
*
* @param value The value to check.
* @returns {boolean} True if the object provided is valid, false otherwise.
*/
function isValid(value) {
return value instanceof Date;
}

let DatePicker = React.createClass({

Expand Down Expand Up @@ -52,18 +43,19 @@ let DatePicker = React.createClass({

getInitialState() {
return {
date: this._getPropsDate(),
date: this._isControlled() ? this._getControlledDate() : this.props.defaultDate,
dialogDate: new Date(),
};
},

/**
* If this is a controlled input, rather than checking all the possible dates for changes
* ourselves, just assign the current props date and let setState do the checking.
*/
componentWillReceiveProps(nextProps) {
if (nextProps.hasOwnProperty('value') || nextProps.hasOwnProperty('valueLink')) {
this.setDate(this._getPropsDate(nextProps));
if (this._isControlled()) {
let newDate = this._getControlledDate(nextProps);
if (!DateTime.isEqualDate(this.state.date, newDate)) {
this.setState({
date: newDate,
});
}
}
},

Expand Down Expand Up @@ -116,11 +108,10 @@ let DatePicker = React.createClass({
return this.state.date;
},

/**
* Setting the state will update the date here and also re-render the TextField with
* the new value.
*/
setDate(d) {
if (process.env.NODE_ENV !== 'production' && this._isControlled()) {
console.error('Cannot call DatePicker.setDate when value or valueLink is defined as a property.');
}
this.setState({
date: d,
});
Expand All @@ -132,9 +123,7 @@ let DatePicker = React.createClass({
openDialog() {
this.setState({
dialogDate: this.getDate(),
// State changes aren't always handled immediately,
// better to wait on the callback.
}, () => this.refs.dialogWindow.show());
}, this.refs.dialogWindow.show);
},

/**
Expand All @@ -145,7 +134,9 @@ let DatePicker = React.createClass({
},

_handleDialogAccept(d) {
this.setDate(d);
if (!this._isControlled()) {
this.setDate(d);
}
if (this.props.onChange) this.props.onChange(null, d);
if (this.props.valueLink) this.props.valueLink.requestChange(d);
},
Expand All @@ -168,13 +159,16 @@ let DatePicker = React.createClass({
//TO DO: open the dialog if input has focus
},

_getPropsDate(props = this.props) {
if (isValid(props.value)) {
_isControlled() {
return this.props.hasOwnProperty('value') ||
this.props.hasOwnProperty('valueLink');
},

_getControlledDate(props = this.props) {
if (DateTime.isDateObject(props.value)) {
return props.value;
} else if (props.valueLink && isValid(props.valueLink.value)) {
} else if (props.valueLink && DateTime.isDateObject(props.valueLink.value)) {
return props.valueLink.value;
} else if (isValid(props.defaultDate)) {
return props.defaultDate;
}
},

Expand Down
4 changes: 4 additions & 0 deletions src/utils/date-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ module.exports = {
!(this.isAfterDate(dateToCheck, endDate)));
},

isDateObject(d) {
return d instanceof Date;
},

monthDiff(d1, d2) {
let m;
m = (d1.getFullYear() - d2.getFullYear()) * 12;
Expand Down

0 comments on commit 1b190d0

Please sign in to comment.