diff --git a/docs/src/app/components/pages/components/TimePicker/ExampleComplex.jsx b/docs/src/app/components/pages/components/TimePicker/ExampleComplex.jsx
index e9502cbc2a18c2..23cc6912499d1e 100644
--- a/docs/src/app/components/pages/components/TimePicker/ExampleComplex.jsx
+++ b/docs/src/app/components/pages/components/TimePicker/ExampleComplex.jsx
@@ -3,30 +3,30 @@ import TimePicker from 'material-ui/lib/time-picker/time-picker';
export default class TimePickerExampleComplex extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {value24: null, value12: null};
+ }
- handleChangeTimePicker12 = (err, time) => {
- this.refs.picker12hr.setTime(time);
+ handleChangeTimePicker24 = (e, date) => {
+ this.setState({value24: date});
};
- handleChangeTimePicker24 = (err, time) => {
- this.refs.picker24hr.setTime(time);
+ handleChangeTimePicker12 = (e, date) => {
+ this.setState({value12: date});
};
render() {
return (
-
-
+
);
}
diff --git a/src/time-picker/clock.jsx b/src/time-picker/clock.jsx
index f5384a27a9a388..e56e00a24333a9 100644
--- a/src/time-picker/clock.jsx
+++ b/src/time-picker/clock.jsx
@@ -28,7 +28,7 @@ const Clock = React.createClass({
getInitialState() {
return {
muiTheme: this.context.muiTheme || getMuiTheme(),
- selectedTime: this.props.initialTime,
+ selectedTime: this.props.initialTime || new Date(),
mode: 'hour',
};
},
@@ -36,7 +36,7 @@ const Clock = React.createClass({
componentWillReceiveProps(nextProps, nextContext) {
this.setState({
muiTheme: nextContext.muiTheme || this.state.muiTheme,
- selectedTime: nextProps.initialTime,
+ selectedTime: nextProps.initialTime || new Date(),
});
},
diff --git a/src/time-picker/time-picker.jsx b/src/time-picker/time-picker.jsx
index 7ec7d557259cf9..34c2cb960d5a2d 100644
--- a/src/time-picker/time-picker.jsx
+++ b/src/time-picker/time-picker.jsx
@@ -1,4 +1,6 @@
import React from 'react';
+import warning from 'warning';
+import DateTime from '../utils/date-time.js';
import TimePickerDialog from './time-picker-dialog';
import TextField from '../text-field';
import getMuiTheme from '../styles/getMuiTheme';
@@ -76,6 +78,16 @@ const TimePicker = React.createClass({
* Override the inline-styles of TimePicker's TextField element.
*/
textFieldStyle: React.PropTypes.object,
+
+ /**
+ * Sets the time for the Time Picker programmatically.
+ */
+ value: React.PropTypes.object,
+
+ /**
+ * Wordings used inside the button of the dialog.
+ */
+ wordings: React.PropTypes.object,
},
contextTypes: {
@@ -94,47 +106,41 @@ const TimePicker = React.createClass({
getInitialState() {
return {
- time: this.props.defaultTime || emptyTime,
+ time: this._isControlled() ? this._getControlledTime() : this.props.defaultTime,
dialogTime: new Date(),
muiTheme: this.context.muiTheme || getMuiTheme(),
};
},
- formatTime(date) {
- let hours = date.getHours();
- let mins = date.getMinutes().toString();
-
- if (this.props.format === 'ampm') {
- const isAM = hours < 12;
- hours = hours % 12;
- const additional = isAM ? ' am' : ' pm';
- hours = (hours || 12).toString();
-
- if (mins.length < 2 ) mins = `0${mins}`;
-
- if (this.props.pedantic) {
- // Treat midday/midnight specially http://www.nist.gov/pml/div688/times.cfm
- if (hours === '12' && mins === '00') {
- return additional === ' pm' ? '12 noon' : '12 midnight';
- }
- }
-
- return hours + (mins === '00' ? '' : `:${mins}`) + additional;
+ componentWillReceiveProps(nextProps, nextContext) {
+ const newState = this.state;
+ if (nextContext.muiTheme) {
+ newState.muiTheme = nextContext.muiTheme;
}
-
- hours = hours.toString();
-
- if (hours.length < 2) hours = `0${hours}`;
- if (mins.length < 2) mins = `0${mins}`;
-
- return `${hours}:${mins}`;
+ newState.time = this._getControlledTime(nextProps);
+ this.setState(newState);
},
+
+ /**
+ * Deprecated.
+ * returns timepicker value.
+ **/
getTime() {
+ warning(false, `getTime() method is deprecated. Use the defaultTime property
+ instead. Or use the TimePicker as a controlled component with the value
+ property.`);
return this.state.time;
},
+ /**
+ * Deprecated
+ * sets timepicker value.
+ **/
setTime(time) {
+ warning(false, `setTime() method is deprecated. Use the defaultTime property
+ instead. Or use the TimePicker as a controlled component with the value
+ property.`);
this.setState({time: time ? time : emptyTime});
},
@@ -147,14 +153,15 @@ const TimePicker = React.createClass({
openDialog() {
this.setState({
- dialogTime: this.getTime(),
+ dialogTime: this.state.time,
});
-
this.refs.dialogWindow.show();
},
_handleDialogAccept(t) {
- this.setTime(t);
+ this.setState({
+ time: t,
+ });
if (this.props.onChange) this.props.onChange(null, t);
},
@@ -171,6 +178,18 @@ const TimePicker = React.createClass({
if (this.props.onTouchTap) this.props.onTouchTap(e);
},
+ _isControlled() {
+ return this.props.value !== null;
+ },
+
+ _getControlledTime(props = this.props) {
+ let result = null;
+ if (DateTime.isDateObject(props.value)) {
+ result = props.value;
+ }
+ return result;
+ },
+
render() {
const {
autoOk,
@@ -181,6 +200,7 @@ const TimePicker = React.createClass({
onDismiss,
style,
textFieldStyle,
+ pedantic,
...other,
} = this.props;
@@ -197,7 +217,7 @@ const TimePicker = React.createClass({
{...other}
style={textFieldStyle}
ref="input"
- value={time === emptyTime ? null : this.formatTime(time)}
+ value={time === emptyTime ? null : DateTime.formatTime(time, format, pedantic)}
onFocus={this._handleInputFocus}
onTouchTap={this._handleInputTouchTap}
/>
diff --git a/src/utils/date-time.js b/src/utils/date-time.js
index f814f4b43a8e37..0758711b466564 100644
--- a/src/utils/date-time.js
+++ b/src/utils/date-time.js
@@ -49,6 +49,24 @@ export default {
return newDate;
},
+ addHours(d, hours) {
+ const newDate = this.clone(d);
+ newDate.setHours(d.getHours() + hours);
+ return newDate;
+ },
+
+ addMinutes(d, minutes) {
+ const newDate = this.clone(d);
+ newDate.setMinutes(d.getMinutes() + minutes);
+ return newDate;
+ },
+
+ addSeconds(d, seconds) {
+ const newDate = this.clone(d);
+ newDate.setSeconds(d.getMinutes() + seconds);
+ return newDate;
+ },
+
clone(d) {
return new Date(d.getTime());
},
@@ -123,6 +141,46 @@ export default {
return `${m}/${d}/${y}`;
},
+ /**
+ * formatTime, extracted from date-picker/date-picker.
+ *
+ * @param date [Date] A Date object.
+ * @param format [String] One of 'ampm', '24hr', defaults to 'ampm'.
+ * @param pedantic [Boolean] Check time-picker/time-picker.jsx file.
+ *
+ * @return String A string representing the formatted time.
+ */
+ formatTime(date, format = 'ampm', pedantic = false) {
+ if (!date) return '';
+ let hours = date.getHours();
+ let mins = date.getMinutes().toString();
+
+ if (format === 'ampm') {
+ let isAM = hours < 12;
+ hours = hours % 12;
+ let additional = isAM ? ' am' : ' pm';
+ hours = (hours || 12).toString();
+
+ if (mins.length < 2 ) mins = `0${mins}`;
+
+ if (pedantic) {
+ // Treat midday/midnight specially http://www.nist.gov/pml/div688/times.cfm
+ if (hours === '12' && mins === '00') {
+ return additional === ' pm' ? '12 noon' : '12 midnight';
+ }
+ }
+
+ return hours + (mins === '00' ? '' : `:${mins}`) + additional;
+ }
+
+ hours = hours.toString();
+
+ if (hours.length < 2) hours = `0${hours}`;
+ if (mins.length < 2) mins = `0${mins}`;
+
+ return `${hours}:${mins}`;
+ },
+
isEqualDate(d1, d2) {
return d1 && d2 &&
(d1.getFullYear() === d2.getFullYear()) &&
@@ -165,4 +223,12 @@ export default {
return ~~(this.monthDiff(d1, d2) / 12);
},
+ isEqualTime(d1, d2) {
+ return d1 && d2 &&
+ (d1.getHours() === d2.getHours()) &&
+ (d1.getMinutes() === d2.getMinutes()) &&
+ (d1.getSeconds() === d2.getSeconds()) &&
+ (d1.getMilliseconds() === d2.getMilliseconds());
+ },
+
};
diff --git a/test/time-picker/time-picker-spec.js b/test/time-picker/time-picker-spec.js
new file mode 100644
index 00000000000000..aa3d9c864a3645
--- /dev/null
+++ b/test/time-picker/time-picker-spec.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import TextField from 'text-field';
+import TimePicker from 'time-picker/time-picker';
+import DateTime from 'utils/date-time';
+import TestUtils from 'react-addons-test-utils';
+
+describe('TimePicker', () => {
+
+ it('has to give value prop precedence over defaultTime', () => {
+ let initialTime = new Date(1448967059892); // Tue, 01 Dec 2015 10:50:59 GMT
+ let valueTime = DateTime.addHours(initialTime, 2);
+
+ let render = TestUtils.renderIntoDocument(
+
+ );
+
+ let timeTextField = TestUtils.findRenderedComponentWithType(render, TextField);
+
+ expect(timeTextField.props.value, DateTime.formatTime(valueTime));
+ });
+
+ it('takes defaulTime prop to set first value when value prop is missing', () => {
+ let initialTime = new Date(1448967059892); // Tue, 01 Dec 2015 10:50:59 GMT
+
+ let render = TestUtils.renderIntoDocument(
+
+ );
+
+ let timeTextField = TestUtils.findRenderedComponentWithType(render, TextField);
+
+ expect(timeTextField.props.value, DateTime.formatTime(initialTime));
+ });
+
+ it('shows value prop if defaultTime is missing', () => {
+ let initialTime = null;
+ let valueTime = new Date(1448967059892); // Tue, 01 Dec 2015 10:50:59 GM
+
+ let render = TestUtils.renderIntoDocument(
+
+ );
+
+ let timeTextField = TestUtils.findRenderedComponentWithType(render, TextField);
+
+ expect(timeTextField.props.value, DateTime.formatTime(valueTime));
+ });
+
+});