diff --git a/README.md b/README.md
index c55c6060ce..94b2bdbd0b 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ Check [index.js](https://github.com/xgfe/react-native-datepicker/blob/master/exa
style={{width: 200}}
date={this.state.date}
mode="date"
+ placeholder="select date"
format="YYYY-MM-DD"
minDate="2016-05-01"
maxDate="2016-06-01"
@@ -59,6 +60,7 @@ You can check [index.js](https://github.com/xgfe/react-native-datepicker/blob/ma
| duration | 300 | `number` | Specify the animation duration of datepicker.|
| customStyles | - | `number` | The hook of customize datepicker style, same as the native style. `dateTouchBody`, `dateInput`...|
| showIcon | true | `boolean` | Controller whether or not show the icon |
+| placeholder | '' | `string` | The placeholder show when this.props.date is falsy |
## Methods
diff --git a/example/index.android.js b/example/index.android.js
index 73fa08f094..14bdf655a8 100644
--- a/example/index.android.js
+++ b/example/index.android.js
@@ -18,7 +18,7 @@ class example extends Component {
super(props);
this.state = {
- date: '2016-05-11',
+ date: '',
time: '20:00',
datetime: '2016-05-05 20:00',
datetime1: '2016-05-05 20:00'
@@ -35,6 +35,7 @@ class example extends Component {
style={{width: 200}}
date={this.state.date}
mode="date"
+ placeholder="placeholder"
format="YYYY-MM-DD"
minDate="2016-05-01"
maxDate="2016-06-01"
diff --git a/index.js b/index.js
index 4cd41ee649..c608d364ab 100644
--- a/index.js
+++ b/index.js
@@ -24,26 +24,7 @@ class DatePicker extends Component {
constructor(props) {
super(props);
- this.mode = this.props.mode || 'date';
-
- this.format = this.props.format || FORMATS[this.mode];
- // component height: 216(DatePickerIOS) + 1(borderTop) + 42(marginTop), IOS only
- this.height = 259;
- // slide animation duration time, default to 300ms, IOS only
- this.duration = this.props.duration || 300;
-
- this.confirmBtnText = this.props.confirmBtnText || '确定';
- this.cancelBtnText = this.props.cancelBtnText || '取消';
-
- this.iconSource = this.props.iconSource || require('./date_icon.png');
- this.customStyles = this.props.customStyles || {};
-
- // whether or not show the icon
- if (typeof this.props.showIcon === 'boolean') {
- this.showIcon = this.props.showIcon;
- } else {
- this.showIcon = true;
- }
+ this.format = this.props.format || FORMATS[this.props.mode];
this.state = {
date: this.getDate(),
@@ -79,8 +60,8 @@ class DatePicker extends Component {
Animated.timing(
this.state.animatedHeight,
{
- toValue: this.height,
- duration: this.duration
+ toValue: this.props.height,
+ duration: this.props.duration
}
).start();
} else {
@@ -120,15 +101,15 @@ class DatePicker extends Component {
this.props.onDateChange(this.getDateStr(this.state.date), this.state.date);
}
}
-
+
getTitleElement() {
const {date, placeholder} = this.props;
if (!date && placeholder) {
- return ({placeholder});
+ return ({placeholder});
}
- return ({this.getDateStr()});
+ return ({this.getDateStr()});
}
-
+
onDatePicked({action, year, month, day}) {
if (action !== DatePickerAndroid.dismissedAction) {
this.setState({
@@ -183,13 +164,13 @@ class DatePicker extends Component {
} else {
// 选日期
- if (this.mode === 'date') {
+ if (this.props.mode === 'date') {
DatePickerAndroid.open({
date: this.state.date,
minDate: this.props.minDate && this.getDate(this.props.minDate),
maxDate: this.props.maxDate && this.getDate(this.props.maxDate)
}).then(this.onDatePicked);
- } else if (this.mode === 'time') {
+ } else if (this.props.mode === 'time') {
// 选时间
let timeMoment = Moment(this.state.date);
@@ -199,7 +180,7 @@ class DatePicker extends Component {
minute: timeMoment.minutes(),
is24Hour: !this.format.match(/h|a/)
}).then(this.onTimePicked);
- } else if (this.mode === 'datetime') {
+ } else if (this.props.mode === 'datetime') {
// 选日期和时间
DatePickerAndroid.open({
@@ -214,6 +195,8 @@ class DatePicker extends Component {
}
render() {
+ let customStyles = this.props.customStyles;
+ this.format = this.props.format || FORMATS[this.props.mode];
return (
-
-
+
+
{this.getTitleElement()}
- {this.showIcon && }
{Platform.OS === 'ios' &&
this.setState({date: date})}
- style={[Style.datePicker, this.customStyles.datePicker]}
+ style={[Style.datePicker, customStyles.datePicker]}
/>
- {this.cancelBtnText}
+ {this.props.cancelBtnText}
- {this.confirmBtnText}
+ {this.props.confirmBtnText}
@@ -283,4 +266,42 @@ class DatePicker extends Component {
}
}
+DatePicker.defaultProps = {
+ mode: 'date',
+ date: '',
+ // component height: 216(DatePickerIOS) + 1(borderTop) + 42(marginTop), IOS only
+ height: 259,
+
+ // slide animation duration time, default to 300ms, IOS only
+ duration: 300,
+ confirmBtnText: '确定',
+ cancelBtnText: '取消',
+ iconSource: require('./date_icon.png'),
+ customStyles: {},
+
+ // whether or not show the icon
+ showIcon: true,
+ disabled: false,
+ placeholder: ''
+};
+
+DatePicker.propTypes = {
+ mode: React.PropTypes.oneOf(['date', 'datetime', 'time']),
+ date: React.PropTypes.oneOfType([React.PropTypes.string, function(props, propName) {
+ if (!(props[propName] instanceof Date)) {
+ return new Error('Should be string or Date');
+ }
+ }]),
+ height: React.PropTypes.number,
+ duration: React.PropTypes.number,
+ confirmBtnText: React.PropTypes.string,
+ cancelBtnText: React.PropTypes.string,
+ iconSource: React.PropTypes.oneOfType([React.PropTypes.number, React.PropTypes.object]),
+ customStyles: React.PropTypes.object,
+ showIcon: React.PropTypes.bool,
+ disabled: React.PropTypes.bool,
+ onDateChange: React.PropTypes.func,
+ placeholder: React.PropTypes.string
+};
+
export default DatePicker;
diff --git a/package.json b/package.json
index ec88c22217..71c3a457d8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-datepicker",
- "version": "1.3.0",
+ "version": "1.3.1",
"description": "react native datePicker component for both Android and IOS, useing DatePikcerAndroid, TimePickerAndroid and DatePickerIOS",
"main": "index.js",
"scripts": {
@@ -33,14 +33,15 @@
"chai": "^3.5.0",
"coveralls": "^2.11.9",
"cz-conventional-changelog": "^1.1.6",
- "enzyme": "^2.3.0",
+ "enzyme": "^2.4.0",
"istanbul": "^1.0.0-alpha.2",
+ "jsdom": "^9.4.1",
"mocha": "^2.5.2",
"pre-commit": "^1.1.3",
- "react": "15.0.2",
- "react-addons-test-utils": "15.0.2",
- "react-dom": "15.0.2",
- "react-native": "^0.26.0",
+ "react": "^15.1.0",
+ "react-addons-test-utils": "^15.1.0",
+ "react-dom": "^15.1.0",
+ "react-native": "^0.28.0",
"react-native-mock": "^0.2.3",
"sinon": "^1.17.4"
},
diff --git a/test/index.test.js b/test/index.test.js
index 4930563723..78121f823e 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -1,11 +1,13 @@
-import React from 'react';
+import React, {Component} from 'react';
import {
Animated,
- Platform
+ Platform,
+ Image,
+ Text,
+ View
} from 'react-native';
-import {shallow} from 'enzyme';
+import {shallow, mount} from 'enzyme';
import Moment from 'moment';
-import DatePicker from '../index';
import {expect} from 'chai';
import sinon from 'sinon';
@@ -21,29 +23,52 @@ m._load = function (request, parent, isMain) {
return originalLoader(request, parent, isMain);
};
+/*---------------- mock DOM ----------------*/
+import {jsdom} from 'jsdom';
+var exposedProperties = ['window', 'navigator', 'document'];
+
+global.document = jsdom('');
+global.window = document.defaultView;
+Object.keys(document.defaultView).forEach((property) => {
+ if (typeof global[property] === 'undefined') {
+ exposedProperties.push(property);
+ global[property] = document.defaultView[property];
+ }
+});
+
+global.navigator = {
+ userAgent: 'node.js'
+};
+
+global.ErrorUtils = {
+ setGlobalHandler: () => {}
+};
+
+var DatePicker = require('../index').default;
+
describe('DatePicker:', () => {
it('initialize', () => {
- const wrapper = shallow();
+
+ const wrapper = mount();
const datePicker = wrapper.instance();
- expect(datePicker.mode).to.equal('date');
+ expect(wrapper.prop('mode')).to.equal('date');
expect(datePicker.format).to.equal('YYYY-MM-DD');
- expect(datePicker.duration).to.equal(300);
- expect(datePicker.height).to.above(200);
- expect(datePicker.confirmBtnText).to.equal('确定');
- expect(datePicker.cancelBtnText).to.equal('取消');
- expect(datePicker.iconSource).to.deep.equal(require('../date_icon.png'));
- expect(datePicker.customStyles).to.deep.equal({});
- expect(datePicker.showIcon).to.equal(true);
- expect(wrapper.find('Image').length).to.equal(1);
+ expect(wrapper.prop('duration')).to.equal(300);
+ expect(wrapper.prop('height')).to.above(200);
+ expect(wrapper.prop('confirmBtnText')).to.equal('确定');
+ expect(wrapper.prop('cancelBtnText')).to.equal('取消');
+ expect(wrapper.prop('iconSource')).to.deep.equal(require('../date_icon.png'));
+ expect(wrapper.prop('customStyles')).to.deep.equal({});
+ expect(wrapper.prop('showIcon')).to.equal(true);
expect(wrapper.state('date')).to.be.a('date');
- expect(wrapper.state('disabled')).to.equal(undefined);
+ expect(wrapper.state('disabled')).to.equal(false);
expect(wrapper.state('modalVisible')).to.equal(false);
expect(wrapper.state('animatedHeight')).to.deep.equal(new Animated.Value(0));
- const wrapper1 = shallow(
+ const wrapper1 = mount(
{
);
const datePicker1 = wrapper1.instance();
-
- expect(datePicker1.mode).to.equal('datetime');
+ expect(wrapper1.prop('mode')).to.equal('datetime');
expect(datePicker1.format).to.equal('YYYY/MM/DD');
- expect(datePicker1.duration).to.equal(400);
- expect(datePicker1.confirmBtnText).to.equal('Confirm');
- expect(datePicker1.cancelBtnText).to.equal('Cancel');
- expect(datePicker1.iconSource).to.deep.equal({});
- expect(datePicker1.customStyles).to.deep.equal({testStyle: 123});
- expect(datePicker1.showIcon).to.equal(false);
- expect(wrapper1.find('Image').length).to.equal(0);
+ expect(wrapper1.prop('duration')).to.equal(400);
+ expect(wrapper1.prop('confirmBtnText')).to.equal('Confirm');
+ expect(wrapper1.prop('cancelBtnText')).to.equal('Cancel');
+ expect(wrapper1.prop('iconSource')).to.deep.equal({});
+ expect(wrapper1.prop('customStyles')).to.deep.equal({testStyle: 123});
+ expect(wrapper1.prop('showIcon')).to.equal(false);
expect(wrapper1.state('date')).to.deep.equal(Moment('2016-05-11', 'YYYY-MM-DD').toDate());
expect(wrapper1.state('disabled')).to.equal(true);
+
+ // find not work with mount, and defaultProps not work with shallow...
+ const wrapper2 = shallow();
+ expect(wrapper2.find('Image')).to.have.length(1);
+ expect(wrapper2.instance().getDateStr()).to.equal('2016-09-09');
+
+ const wrapper3 = shallow();
+ expect(wrapper3.find('Image')).to.have.length(0);
+ expect(wrapper3.instance().getDateStr()).to.equal('Invalid date');
});
it('setModalVisible', () => {
@@ -212,26 +244,26 @@ describe('DatePicker:', () => {
Platform.OS = 'android';
expect(datePicker.onPressDate).to.not.throw(Error);
- datePicker.mode = 'datetime';
+ wrapper.setProps({mode: 'datetime'});
expect(datePicker.onPressDate).to.not.throw(Error);
- datePicker.mode = 'time';
+ wrapper.setProps({mode: 'time'});
expect(datePicker.onPressDate).to.not.throw(Error);
- datePicker.mode = 'tttt';
+ wrapper.setProps({mode: 'tttt'});
expect(datePicker.onPressDate).to.throw(Error);
});
-
+
it('getTitleElement - with placeholder', () => {
const placeholder = 'Please pick a date';
- const wrapper = shallow();
+ const wrapper = mount();
const datePicker = wrapper.instance();
expect(datePicker.getTitleElement().props.children).to.equal(placeholder);
});
it('getTitleElement - without placeholder', () => {
- const wrapper = shallow();
+ const wrapper = mount();
const datePicker = wrapper.instance();
expect(datePicker.getTitleElement().props.children).to.equal(datePicker.getDateStr());