diff --git a/docs/src/app/components/pages/components/DatePicker/ExampleKeyboardInput.js b/docs/src/app/components/pages/components/DatePicker/ExampleKeyboardInput.js
new file mode 100644
index 00000000000000..923db9b79c678b
--- /dev/null
+++ b/docs/src/app/components/pages/components/DatePicker/ExampleKeyboardInput.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import DatePicker from 'material-ui/DatePicker';
+
+/**
+ * This example allows you to use keyboard to write date.
+ *
+ * Unfortunately by now it is only working with default locale (`en-US`).
+ * In other cases `keyboardEnabled` prop will be ignored.
+ * Also it will not work if it is controlled component or has disabled dates.
+ */
+const DatePickerExampleKeyboardInput = () => (
+
+
+
+);
+
+export default DatePickerExampleKeyboardInput;
diff --git a/docs/src/app/components/pages/components/DatePicker/Page.js b/docs/src/app/components/pages/components/DatePicker/Page.js
index 1f2f86026ba656..595c01d94a4282 100644
--- a/docs/src/app/components/pages/components/DatePicker/Page.js
+++ b/docs/src/app/components/pages/components/DatePicker/Page.js
@@ -18,6 +18,8 @@ import DatePickerExampleDisableDates from './ExampleDisableDates';
import datePickerExampleDisableDatesCode from '!raw!./ExampleDisableDates';
import DatePickerExampleInternational from './ExampleInternational';
import datePickerExampleInternationalCode from '!raw!./ExampleInternational';
+import DatePickerExampleKeyboardInput from './ExampleKeyboardInput';
+import datePickerExampleKeyboardInputCode from '!raw!./ExampleKeyboardInput';
import datePickerCode from '!raw!material-ui/DatePicker/DatePicker';
const DatePickerPage = () => (
@@ -60,6 +62,12 @@ const DatePickerPage = () => (
>
+
+
+
);
diff --git a/src/DatePicker/DatePicker.js b/src/DatePicker/DatePicker.js
index 03612c2308bb98..e9c8feced3088c 100644
--- a/src/DatePicker/DatePicker.js
+++ b/src/DatePicker/DatePicker.js
@@ -2,6 +2,18 @@ import React, {Component, PropTypes} from 'react';
import {dateTimeFormat, formatIso, isEqualDate} from './dateUtils';
import DatePickerDialog from './DatePickerDialog';
import TextField from '../TextField';
+import IconButton from '../IconButton';
+import DateRangeIcon from '../svg-icons/action/date-range';
+
+export function getStyles() {
+ const styles = {
+ iconButtonStyle: {
+ verticalAlign: 'top',
+ },
+ };
+
+ return styles;
+}
class DatePicker extends Component {
static propTypes = {
@@ -50,6 +62,10 @@ class DatePicker extends Component {
* Disables the DatePicker.
*/
disabled: PropTypes.bool,
+ /**
+ * Text for validation error.
+ */
+ errorText: PropTypes.string,
/**
* Used to change the first day of week. It varies from
* Saturday to Monday between different locales.
@@ -65,6 +81,15 @@ class DatePicker extends Component {
* @returns {any} The formatted date.
*/
formatDate: PropTypes.func,
+ /**
+ * Override the inline-styles of calendar IconButton (it is showing when `keyboardEnabled` is `true`).
+ */
+ iconButtonStyle: PropTypes.object,
+ /**
+ * Tells the datepicker to handle keyboard input.
+ * Will not work if `locale` or `shouldDisableDate` props are specified or if it is controlled component.
+ */
+ keyboardEnabled: PropTypes.bool,
/**
* Locale used for formatting the `DatePicker` date strings. Other than for 'en-US', you
* must provide a `DateTimeFormat` that supports the chosen `locale`.
@@ -140,7 +165,9 @@ class DatePicker extends Component {
container: 'dialog',
disabled: false,
disableYearSelection: false,
+ errorText: 'Enter a valid date in "YYYY-MM-DD" format',
firstDayOfWeek: 1,
+ keyboardEnabled: false,
style: {},
};
@@ -150,11 +177,15 @@ class DatePicker extends Component {
state = {
date: undefined,
+ hasError: false,
+ textDate: '',
};
componentWillMount() {
+ const defaultDate = this.isControlled() ? this.getControlledDate() : this.props.defaultDate;
this.setState({
- date: this.isControlled() ? this.getControlledDate() : this.props.defaultDate,
+ date: defaultDate,
+ textDate: defaultDate ? this.formatDate(defaultDate) : '',
});
}
@@ -164,6 +195,7 @@ class DatePicker extends Component {
if (!isEqualDate(this.state.date, newDate)) {
this.setState({
date: newDate,
+ textDate: this.formatDate(newDate),
});
}
}
@@ -200,10 +232,18 @@ class DatePicker extends Component {
this.openDialog();
}
+ shouldHandleKeyboard() {
+ return this.props.keyboardEnabled && !this.props.disabled &&
+ !this.props.locale && !this.props.shouldDisableDate &&
+ !this.isControlled();
+ }
+
+
handleAccept = (date) => {
if (!this.isControlled()) {
this.setState({
date: date,
+ textDate: this.formatDate(date),
});
}
if (this.props.onChange) {
@@ -212,12 +252,37 @@ class DatePicker extends Component {
};
handleFocus = (event) => {
- event.target.blur();
+ if (!this.shouldHandleKeyboard()) {
+ event.target.blur();
+ }
+
if (this.props.onFocus) {
this.props.onFocus(event);
}
};
+ handleBlur = () => {
+ if (this.shouldHandleKeyboard()) {
+ if (this.getDate()) {
+ this.setState({
+ textDate: this.formatDate(this.getDate()),
+ });
+ }
+
+ this.setState({
+ hasError: !this.getDate() && !!this.state.textDate.trim(),
+ });
+ }
+ }
+
+ handleTextChange = (event, value) => {
+ const parsedDate = this.parseDate(value);
+ this.setState({
+ date: parsedDate,
+ textDate: value,
+ });
+ };
+
handleTouchTap = (event) => {
if (this.props.onTouchTap) {
this.props.onTouchTap(event);
@@ -241,7 +306,9 @@ class DatePicker extends Component {
}
formatDate = (date) => {
- if (this.props.locale) {
+ if (this.props.formatDate) {
+ return this.props.formatDate(date);
+ } else if (this.props.locale) {
const DateTimeFormat = this.props.DateTimeFormat || dateTimeFormat;
return new DateTimeFormat(this.props.locale, {
day: 'numeric',
@@ -253,6 +320,21 @@ class DatePicker extends Component {
}
};
+ parseDate = (textDate) => {
+ // regex to parse date is based on ISO 8601 (YYYY-MM-DD)
+ const reg = /^(\d{4})-(\d{2})-(\d{2})$/;
+ const match = reg.exec(textDate);
+ if (!match) {
+ return;
+ }
+
+ const year = match[1];
+ const month = match[2] === 0 ? 11 : (match[2] - 1);
+ const day = match[3];
+
+ return new Date(year, month, day);
+ };
+
render() {
const {
DateTimeFormat,
@@ -264,7 +346,8 @@ class DatePicker extends Component {
dialogContainerStyle,
disableYearSelection,
firstDayOfWeek,
- formatDate: formatDateProp,
+ formatDate, // eslint-disable-line no-unused-vars
+ iconButtonStyle,
locale,
maxDate,
minDate,
@@ -277,22 +360,36 @@ class DatePicker extends Component {
shouldDisableDate,
style,
textFieldStyle,
+ keyboardEnabled, // eslint-disable-line no-unused-vars
+ errorText,
...other
} = this.props;
const {prepareStyles} = this.context.muiTheme;
- const formatDate = formatDateProp || this.formatDate;
+ const styles = getStyles(this.props, this.context);
return (
+ {this.shouldHandleKeyboard() &&
+
+
+
+ }