Skip to content

Commit ebf64bc

Browse files
committed
Fix #16: Update datetime widget's value when moved in array
1 parent 03552a1 commit ebf64bc

File tree

2 files changed

+74
-56
lines changed

2 files changed

+74
-56
lines changed

src/components/form.js

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,25 @@ export class FormDateTimeInput extends React.Component {
371371
// so that we can only pass valid values
372372
// otherwise keep the value empty if invalid
373373

374+
this.state = {
375+
...this.getStateFromProps(),
376+
showTimePicker: false,
377+
};
378+
379+
this.timeInput = React.createRef();
380+
this.timePickerContainer = React.createRef();
381+
}
382+
383+
getStateFromProps = () => {
374384
let date = '';
375385
let hh = '12';
376386
let mm = '00';
377387
let ss = '00';
378388
let ms = '000';
379389
let ampm = 'am';
380390

381-
if (props.value) {
382-
let d = new Date(props.value);
391+
if (this.props.value) {
392+
let d = new Date(this.props.value);
383393
let year = d.getFullYear().toString().padStart(2, '0');
384394
let month = (d.getMonth() + 1).toString().padStart(2, '0');
385395
let day = d.getDate().toString().padStart(2, '0');
@@ -404,18 +414,29 @@ export class FormDateTimeInput extends React.Component {
404414
ss = ss.toString().padStart(2, '0');
405415
}
406416

407-
this.state = {
408-
date: date,
409-
hh: hh,
410-
mm: mm,
411-
ss: ss,
412-
ms: ms,
413-
ampm: ampm,
414-
showTimePicker: false,
415-
};
417+
return {
418+
date: date, hh: hh, mm: mm, ss: ss, ms: ms, ampm: ampm
419+
}
420+
}
416421

417-
this.timeInput = React.createRef();
418-
this.timePickerContainer = React.createRef();
422+
componentDidUpdate(prevProps, prevState) {
423+
if (prevProps.value !== this.props.value) {
424+
if (this.state.hh !== '' && this.state.hh !== '0' && this.state.hh !== '00') {
425+
426+
let changed = false;
427+
let newState = this.getStateFromProps();
428+
429+
for (let key in newState) {
430+
if (newState[key] !== this.state[key]) {
431+
changed = true;
432+
break;
433+
}
434+
}
435+
436+
if (changed)
437+
this.setState({...newState});
438+
}
439+
}
419440
}
420441

421442
componentDidMount() {
@@ -451,6 +472,10 @@ export class FormDateTimeInput extends React.Component {
451472
return this.props.onChange(event);
452473

453474
let hh = parseInt(this.state.hh);
475+
476+
if (hh === 0)
477+
hh = NaN; // zero value is invalid for 12 hour clock, but will be valid for 24 hour clock
478+
// so we set it to NaN to prevent creating a date object
454479

455480
if (this.state.ampm === 'am') {
456481
if (hh === 12)
@@ -464,10 +489,13 @@ export class FormDateTimeInput extends React.Component {
464489
let mm = this.state.mm.padStart(2, '0');
465490
let ss = this.state.ss.padStart(2, '0');
466491

467-
let date = new Date(this.state.date + 'T' + hh + ':' + mm + ':' + ss + '.' + this.state.ms);
468-
let value = date.toISOString().replace('Z', '+00:00') // make compatible to python
469-
470-
event['target']['value'] = value;
492+
try {
493+
let date = new Date(this.state.date + 'T' + hh + ':' + mm + ':' + ss + '.' + this.state.ms);
494+
event['target']['value'] = date.toISOString().replace('Z', '+00:00') // make compatible to python
495+
} catch (err) {
496+
// invalid date
497+
return this.props.onChange(event);
498+
}
471499

472500
this.props.onChange(event);
473501
}
@@ -477,12 +505,7 @@ export class FormDateTimeInput extends React.Component {
477505
}
478506

479507
handleTimeChange = (value) => {
480-
this.setState({
481-
hh: value.hh,
482-
mm: value.mm,
483-
ss: value.ss,
484-
ampm: value.ampm,
485-
}, this.sendValue);
508+
this.setState({...value}, this.sendValue);
486509
}
487510

488511
showTimePicker = () => {

src/components/widgets.js

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@ import Icon from './icons';
33

44

55
export class TimePicker extends React.Component {
6-
constructor(props) {
7-
super(props);
8-
9-
this.state = {
10-
hh: props.hh || '12',
11-
mm: props.mm || '00',
12-
ss: props.ss || '00',
13-
ampm: props.ampm || 'am',
14-
};
6+
componentWillUnmount() {
7+
let data = {
8+
hh: this.validateValue('hh', this.props.hh).toString().padStart(2, '0'),
9+
mm: this.validateValue('mm', this.props.mm).toString().padStart(2, '0'),
10+
ss: this.validateValue('ss', this.props.ss).toString().padStart(2, '0')
11+
}
12+
this.sendValue(data);
1513
}
1614

17-
componentDidUpdate(prevProps, prevState) {
18-
if (this.state !== prevState)
19-
this.props.onChange(this.state);
15+
sendValue = (data) => {
16+
this.props.onChange(data);
2017
}
2118

2219
validateValue = (name, value) => {
@@ -48,7 +45,7 @@ export class TimePicker extends React.Component {
4845
validValue = validValue.toString().padStart(2, '0');
4946
}
5047

51-
this.setState({[name]: value !== '' ? validValue.toString() : ''});
48+
this.sendValue({[name]: value !== '' ? validValue.toString() : ''});
5249
}
5350

5451
handleKeyDown = (e) => {
@@ -64,34 +61,32 @@ export class TimePicker extends React.Component {
6461
value--;
6562
}
6663

67-
this.setState({[name]: this.validateValue(name, value).toString().padStart(2, '0')});
64+
this.sendValue({[name]: this.validateValue(name, value).toString().padStart(2, '0')});
6865
}
6966

7067
handleSpin = (name, type) => {
71-
this.setState((state) => {
72-
let value = state[name];
73-
74-
if (name === 'ampm') {
75-
value = value === 'am' ? 'pm': 'am';
68+
let value = this.props[name];
69+
70+
if (name === 'ampm') {
71+
value = value === 'am' ? 'pm': 'am';
72+
} else {
73+
value = parseInt(value) || 0;
74+
if (type === 'up') {
75+
value++;
7676
} else {
77-
value = parseInt(value) || 0;
78-
if (type === 'up') {
79-
value++;
80-
} else {
81-
value--;
82-
}
83-
value = this.validateValue(name, value).toString().padStart(2, '0');
77+
value--;
8478
}
79+
value = this.validateValue(name, value).toString().padStart(2, '0');
80+
}
8581

86-
return {[name]: value};
87-
});
82+
this.sendValue({[name]: value});
8883
}
8984

9085
handleBlur = (e) => {
9186
let value = this.validateValue(e.target.dataset.name, parseInt(e.target.value) || 0);
9287

9388
if (value < 10) {
94-
this.setState({[e.target.dataset.name]: value.toString().padStart(2, '0')});
89+
this.sendValue({[e.target.dataset.name]: value.toString().padStart(2, '0')});
9590
}
9691
}
9792

@@ -119,13 +114,13 @@ export class TimePicker extends React.Component {
119114
</div>
120115

121116
<div className="rjf-time-picker-row rjf-time-picker-values">
122-
<div className="rjf-time-picker-col"><input type="text" data-name="hh" value={this.state.hh} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
117+
<div className="rjf-time-picker-col"><input type="text" data-name="hh" value={this.props.hh} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
123118
<div className="rjf-time-picker-col rjf-time-picker-col-sm">:</div>
124-
<div className="rjf-time-picker-col"><input type="text" data-name="mm" value={this.state.mm} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
119+
<div className="rjf-time-picker-col"><input type="text" data-name="mm" value={this.props.mm} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
125120
<div className="rjf-time-picker-col rjf-time-picker-col-sm">:</div>
126-
<div className="rjf-time-picker-col"><input type="text" data-name="ss" value={this.state.ss} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
121+
<div className="rjf-time-picker-col"><input type="text" data-name="ss" value={this.props.ss} onChange={this.handleChange} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} /></div>
127122
<div className="rjf-time-picker-col rjf-time-picker-col-sm"></div>
128-
<div className="rjf-time-picker-col">{this.state.ampm}</div>
123+
<div className="rjf-time-picker-col">{this.props.ampm}</div>
129124
</div>
130125

131126
<div className="rjf-time-picker-row">

0 commit comments

Comments
 (0)