Skip to content

Commit 79a7817

Browse files
authored
Merge pull request 1stQuad#3 from daviidovich/master
Create portal to body/custom container for better widget positioning;
2 parents 96a64a9 + eaa6b52 commit 79a7817

File tree

4 files changed

+121
-19
lines changed

4 files changed

+121
-19
lines changed

lib/DateTimeField.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,8 @@ var DateTimeField = (function (_Component) {
584584
calculatePosition: this.calculatePosition,
585585
showPicker: this.state.showPicker,
586586
startOfWeek: this.props.startOfWeek,
587-
availableDatesStringArray: this.state.availableDatesStringArray
587+
availableDatesStringArray: this.state.availableDatesStringArray,
588+
widgetContainerId: this.props.widgetContainerId
588589
}),
589590
_react2['default'].createElement(
590591
'div',
@@ -658,7 +659,8 @@ var DateTimeField = (function (_Component) {
658659
tabIndex: _propTypes2['default'].string,
659660
validationClass: _propTypes2['default'].string,
660661
startOfWeek: _propTypes2['default'].string,
661-
availableDates: _propTypes2['default'].arrayOf(_propTypes2['default'].object)
662+
availableDates: _propTypes2['default'].arrayOf(_propTypes2['default'].object),
663+
widgetContainerId: _propTypes2['default'].string
662664
},
663665
enumerable: true
664666
}]);

lib/DateTimePicker.js

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ var _react = require('react');
1818

1919
var _react2 = _interopRequireDefault(_react);
2020

21+
var _reactDom = require('react-dom');
22+
23+
var _reactDom2 = _interopRequireDefault(_reactDom);
24+
2125
var _propTypes = require('prop-types');
2226

2327
var _propTypes2 = _interopRequireDefault(_propTypes);
@@ -157,14 +161,18 @@ var DateTimePicker = (function (_Component) {
157161
if (this.props.disabled) return '';
158162

159163
return _react2['default'].createElement(
160-
'div',
161-
{ ref: this.props.widgetRef, className: widgetClass, style: this.props.widgetStyle },
164+
DateTimePickerPortal,
165+
{ widgetContainerId: this.props.widgetContainerId },
162166
_react2['default'].createElement(
163-
'ul',
164-
{ className: 'list-unstyled' },
165-
this.renderDatePicker(),
166-
this.renderSwitchButton(),
167-
this.renderTimePicker()
167+
'div',
168+
{ ref: this.props.widgetRef, className: widgetClass, style: this.props.widgetStyle },
169+
_react2['default'].createElement(
170+
'ul',
171+
{ className: 'list-unstyled' },
172+
this.renderDatePicker(),
173+
this.renderSwitchButton(),
174+
this.renderTimePicker()
175+
)
168176
)
169177
);
170178
}
@@ -209,7 +217,8 @@ var DateTimePicker = (function (_Component) {
209217
setToday: _propTypes2['default'].func,
210218
calculatePosition: _propTypes2['default'].func,
211219
startOfWeek: _propTypes2['default'].string,
212-
availableDatesStringArray: _propTypes2['default'].arrayOf(_propTypes2['default'].string)
220+
availableDatesStringArray: _propTypes2['default'].arrayOf(_propTypes2['default'].string),
221+
widgetContainerId: _propTypes2['default'].string
213222
},
214223
enumerable: true
215224
}]);
@@ -218,4 +227,55 @@ var DateTimePicker = (function (_Component) {
218227
})(_react.Component);
219228

220229
exports['default'] = DateTimePicker;
230+
231+
var DateTimePickerPortal = (function (_Component2) {
232+
_inherits(DateTimePickerPortal, _Component2);
233+
234+
_createClass(DateTimePickerPortal, null, [{
235+
key: 'propTypes',
236+
value: {
237+
widgetContainerId: _propTypes2['default'].string
238+
},
239+
enumerable: true
240+
}]);
241+
242+
function DateTimePickerPortal(props) {
243+
_classCallCheck(this, DateTimePickerPortal);
244+
245+
_get(Object.getPrototypeOf(DateTimePickerPortal.prototype), 'constructor', this).call(this, props);
246+
this.state = {
247+
container: null
248+
};
249+
}
250+
251+
_createClass(DateTimePickerPortal, [{
252+
key: 'componentDidMount',
253+
value: function componentDidMount() {
254+
this.updatePortalContainer();
255+
}
256+
}, {
257+
key: 'componentDidUpdate',
258+
value: function componentDidUpdate(prevProps) {
259+
if (prevProps.widgetContainerId !== this.props.widgetContainerId) {
260+
this.updatePortalContainer();
261+
}
262+
}
263+
}, {
264+
key: 'updatePortalContainer',
265+
value: function updatePortalContainer() {
266+
var containerElem = document.getElementById(this.props.widgetContainerId);
267+
this.setState({
268+
container: containerElem || document.body
269+
});
270+
}
271+
}, {
272+
key: 'render',
273+
value: function render() {
274+
return this.state.container ? _reactDom2['default'].createPortal(this.props.children, this.state.container) : null;
275+
}
276+
}]);
277+
278+
return DateTimePickerPortal;
279+
})(_react.Component);
280+
221281
module.exports = exports['default'];

src/DateTimeField.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ export default class DateTimeField extends Component {
141141
tabIndex: PropTypes.string,
142142
validationClass: PropTypes.string,
143143
startOfWeek: PropTypes.string,
144-
availableDates: PropTypes.arrayOf(PropTypes.object)
144+
availableDates: PropTypes.arrayOf(PropTypes.object),
145+
widgetContainerId: PropTypes.string
145146
};
146147

147148
componentWillReceiveProps = nextProps => {
@@ -680,6 +681,7 @@ export default class DateTimeField extends Component {
680681
showPicker={this.state.showPicker}
681682
startOfWeek={this.props.startOfWeek}
682683
availableDatesStringArray={this.state.availableDatesStringArray}
684+
widgetContainerId={this.props.widgetContainerId}
683685
/>
684686
<div
685687
className={classnames('date ', {

src/DateTimePicker.js

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, {Component} from 'react';
2+
import ReactDOM from 'react-dom';
23
import PropTypes from 'prop-types';
34
import classNames from 'classnames';
45
import DateTimePickerDate from './DateTimePickerDate.js';
@@ -50,7 +51,8 @@ export default class DateTimePicker extends Component {
5051
setToday: PropTypes.func,
5152
calculatePosition: PropTypes.func,
5253
startOfWeek: PropTypes.string,
53-
availableDatesStringArray: PropTypes.arrayOf(PropTypes.string)
54+
availableDatesStringArray: PropTypes.arrayOf(PropTypes.string),
55+
widgetContainerId: PropTypes.string,
5456
};
5557

5658
renderDatePicker = () => {
@@ -164,15 +166,51 @@ export default class DateTimePicker extends Component {
164166
if (this.props.disabled) return ('');
165167

166168
return (
167-
<div ref={this.props.widgetRef} className={widgetClass} style={this.props.widgetStyle}>
168-
<ul className="list-unstyled">
169-
{this.renderDatePicker()}
169+
<DateTimePickerPortal widgetContainerId={this.props.widgetContainerId}>
170+
<div ref={this.props.widgetRef} className={widgetClass} style={this.props.widgetStyle}>
171+
<ul className="list-unstyled">
172+
{this.renderDatePicker()}
170173

171-
{this.renderSwitchButton()}
174+
{this.renderSwitchButton()}
172175

173-
{this.renderTimePicker()}
174-
</ul>
175-
</div>
176+
{this.renderTimePicker()}
177+
</ul>
178+
</div>
179+
</DateTimePickerPortal>
176180
);
177181
}
178182
}
183+
184+
class DateTimePickerPortal extends Component {
185+
static propTypes = {
186+
widgetContainerId: PropTypes.string
187+
};
188+
189+
constructor(props) {
190+
super(props);
191+
this.state = {
192+
container: null
193+
};
194+
}
195+
196+
componentDidMount() {
197+
this.updatePortalContainer();
198+
}
199+
200+
componentDidUpdate(prevProps) {
201+
if (prevProps.widgetContainerId !== this.props.widgetContainerId) {
202+
this.updatePortalContainer();
203+
}
204+
}
205+
206+
updatePortalContainer() {
207+
const containerElem = document.getElementById(this.props.widgetContainerId);
208+
this.setState({
209+
container: containerElem || document.body
210+
});
211+
}
212+
213+
render() {
214+
return this.state.container ? ReactDOM.createPortal(this.props.children, this.state.container) : null;
215+
}
216+
}

0 commit comments

Comments
 (0)