Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,21 @@ See the example app in this repo and the `webpack.config.js` for an example of h
import React from 'react';
import Pikaday from 'react-pikaday';

var MyComponent = React.createClass({
getInitialState: function() {
return {
date: null
class MyComponent extends React.Component {
constructor() {
super();
this.state = {
date: null,
};
},

handleChange: function(date) {
this.setState({
date: date
});
},
this.handleChange = this.handleChange.bind(this);
}

render: function() {
var date = this.state.date;
handleChange(date) {
this.setState({ date });
}

render() {
const date = this.state.date;
return (
<div>
<p>
Expand All @@ -61,7 +60,7 @@ var MyComponent = React.createClass({
</div>
);
}
});
}
```

## Properties
Expand Down
2 changes: 1 addition & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var webpackConfig = {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules\/)/,
exclude: /node_modules/,
loader: 'babel-loader'
},
],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-2": "^6.11.0",
"chai": "^1.9.1",
"chai": "^1.10.0",
"css-loader": "^0.23.1",
"eslint": "^3.2.2",
"eslint-plugin-react": "^6.0.0",
Expand Down
59 changes: 28 additions & 31 deletions src/Pikaday.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
import React from 'react';
import Pikaday from 'pikaday';

var ReactPikaday = React.createClass({

propTypes: {
value: React.PropTypes.instanceOf(Date),
onChange: React.PropTypes.func,
initialOptions: React.PropTypes.object,

valueLink: React.PropTypes.shape({
value: React.PropTypes.instanceOf(Date),
requestChange: React.PropTypes.func.isRequired
})
},

getDefaultProps: function() {
return {
initialOptions: {}
};
},

getValueLink: function(props) {
class ReactPikaday extends React.Component {
getValueLink(props) {
return props.valueLink || {
value: props.value,
requestChange: props.onChange
};
},
}

setDateIfChanged: function(newDate, prevDate) {
setDateIfChanged(newDate, prevDate) {
var newTime = newDate ? newDate.getTime() : null;
var prevTime = prevDate ? prevDate.getTime() : null;

Expand All @@ -38,20 +20,20 @@ var ReactPikaday = React.createClass({
}
this._picker.setDate(newDate, true); // 2nd param = don't call onSelect
}
},
}

// user props to pass down to the underlying DOM node
getDomProps: function() {
getDomProps() {
var restProps = {};
for (var propKey in this.props) {
if (this.props.hasOwnProperty(propKey) && !ReactPikaday.propTypes[propKey]) {
restProps[propKey] = this.props[propKey];
}
}
return restProps
},
}

componentDidMount: function() {
componentDidMount() {
var el = this.refs.pikaday;

this._picker = new Pikaday({
Expand All @@ -61,20 +43,35 @@ var ReactPikaday = React.createClass({
});

this.setDateIfChanged(this.getValueLink(this.props).value);
},
}

componentWillReceiveProps: function(nextProps) {
componentWillReceiveProps(nextProps) {
var newDate = this.getValueLink(nextProps).value;
var lastDate = this.getValueLink(this.props).value;

this.setDateIfChanged(newDate, lastDate);
},
}

render: function() {
render() {
return (
<input type="text" ref="pikaday" {...this.getDomProps()} />
);
}
});
}

ReactPikaday.defaultProps = {
initialOptions: {},
};

ReactPikaday.propTypes = {
value: React.PropTypes.instanceOf(Date),
onChange: React.PropTypes.func,
initialOptions: React.PropTypes.object,

valueLink: React.PropTypes.shape({
value: React.PropTypes.instanceOf(Date),
requestChange: React.PropTypes.func.isRequired
}),
};

export default ReactPikaday;
141 changes: 90 additions & 51 deletions src/__tests__/main.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import LinkedStateMixin from 'react-addons-linked-state-mixin';
import {expect} from 'chai';
import { expect } from 'chai';
import TU from 'react-addons-test-utils';

import Pikaday from '../Pikaday';
Expand All @@ -17,21 +18,25 @@ describe('Pikaday', () => {
describe('updating the date in Pikaday calls handleChange', () => {

it('works manually', function() {
var Form = React.createClass({
getInitialState: function() {
return { date: null };
},
class Form extends React.Component {
constructor() {
super();
this.state = {
date: null,
};
this.handleChange = this.handleChange.bind(this);
}

handleChange: function(date) {
this.setState({ date: date });
},
handleChange(date) {
this.setState({ date });
}

render: function() {
render() {
return (
<Pikaday ref="pikaday" value={this.state.date} onChange={this.handleChange} />
);
)
}
});
}

var component = render(<Form />);
var pikaday = component.refs.pikaday._picker;
Expand All @@ -40,20 +45,30 @@ describe('Pikaday', () => {
expect(component.state.date).to.be.eql(new Date(2014, 0, 1));
});

it('works with LinkedStateMixin', function() {
var Form = React.createClass({
mixins: [ LinkedStateMixin ],
it('works with two-way binding', function() {
class Form extends React.Component {
constructor() {
super();
this.state = {
date: null,
};
this.handleChange = this.handleChange.bind(this);
}

getInitialState: function() {
return { date: null };
},
handleChange(date) {
this.setState({ date });
}

render: function() {
render() {
const valueLink = {
value: this.state.date,
requestChange: this.handleChange,
};
return (
<Pikaday ref="pikaday" valueLink={this.linkState('date')} />
<Pikaday ref="pikaday" valueLink={valueLink} />
);
}
});
}

var component = render(<Form />);
var pikaday = component.refs.pikaday._picker;
Expand All @@ -67,42 +82,56 @@ describe('Pikaday', () => {
describe('setting the passed-in value sets the rendered date', () => {

it('works manually', () => {
var Form = React.createClass({
getInitialState: function() {
return { date: new Date(2014, 0, 1) };
},
class Form extends React.Component {
constructor() {
super();
this.state = {
date: new Date(2014, 0, 1),
};
this.handleChange = this.handleChange.bind(this);
}

handleChange: function(date) {
this.setState({ date: date });
},
handleChange(date) {
this.setState({ date });
}

render: function() {
render() {
return (
<Pikaday ref="pikaday" value={this.state.date} onChange={this.handleChange} />
);
}
});
}

var component = render(<Form />);

var input = TU.findRenderedDOMComponentWithTag(component, 'input');
expect(input.value).to.be.eql('2014-01-01');
});

it('works with LinkedStateMixin', function() {
var Form = React.createClass({
mixins: [ LinkedStateMixin ],
it('works with two-way binding', function() {
class Form extends React.Component {
constructor() {
super();
this.state = {
date: new Date(2014, 0, 1),
};
this.handleChange = this.handleChange.bind(this);
}

getInitialState: function() {
return { date: new Date(2014, 0, 1) };
},
handleChange(date) {
this.setState({ date });
}

render: function() {
render() {
const valueLink = {
value: this.state.date,
requestChange: this.handleChange,
};
return (
<Pikaday ref="pikaday" valueLink={this.linkState('date')} />
<Pikaday ref="pikaday" valueLink={valueLink} />
);
}
});
}

var component = render(<Form />);

Expand All @@ -113,26 +142,36 @@ describe('Pikaday', () => {
});

describe('clearing the value', () => {
it('works with LinkedStateMixin', function () {
var Form = React.createClass({
mixins: [ LinkedStateMixin ],
it('works with two-way binding', function () {
class Form extends React.Component {
constructor() {
super();
this.state = {
date: new Date(2014, 0, 1),
};
this.handleChange = this.handleChange.bind(this);
}

getInitialState: function() {
return { date: new Date(2014, 0, 1) };
},
handleChange(date) {
this.setState({ date });
}

render: function() {
render() {
const valueLink = {
value: this.state.date,
requestChange: this.handleChange,
};
return (
<div>
<Pikaday ref="pikaday" valueLink={this.linkState('date')} />
<Pikaday ref="pikaday" valueLink={valueLink} />
<button ref="clearBtn"
onClick={() => this.setState({ date: null })}>
Clear
</button>
</div>
);
}
});
}

var component = render(<Form />);

Expand All @@ -149,13 +188,13 @@ describe('Pikaday', () => {
it('passes options to pikaday plugin', function() {
var minDate = new Date(2014, 0, 1);
let result;
var Form = React.createClass({
render: function() {
class Form extends React.Component {
render() {
return (
<Pikaday ref={({ _picker }) => result = _picker._o.minDate } initialOptions={{ minDate }}/>
);
}
});
}

TU.renderIntoDocument(<Form />);

Expand Down