Skip to content

Commit 15ae828

Browse files
author
=
committed
DateTimePicker: option to render Time part either as Masked Text or as Dropdown
1 parent 0fb2e99 commit 15ae828

15 files changed

+307
-70
lines changed
16.3 KB
Loading
15 KB
Loading
13.7 KB
Loading
21.6 KB
Loading
20.5 KB
Loading

docs/documentation/docs/controls/DateTimePicker.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ Here are some examples of the control:
1313
**DateTime Picker Date Only**
1414
![DateTimePicker Date Only](../assets/DateTimePicker-dateOnly.png)
1515

16+
**DateTime Picker No Seconds**
17+
![DateTimePicker Date Only](../assets/DateTimePicker-noseconds.png)
18+
19+
**DateTime Picker Dropdowns for Time Part**
20+
![DateTimePicker Date Only](../assets/DateTimePicker-dropdown.png)
21+
1622
## How to use this control in your solutions
1723

1824
- Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../#getting-started) page for more information about installing the dependency.
@@ -60,6 +66,15 @@ The `DateTimePicker` control can be configured with the following properties:
6066
| value | Date | no | Default value of the DatePicker, if any |
6167
| onChange | function | no | Callback issued when date or time is changed |
6268
| showSeconds | boolean | no | Specifies, if seconds dropdown should be shown, defaults to false. |
69+
| timeDisplayControlType | TimeDisplayControlType | no | Specifies what type of control to use when rendering time part. |
70+
| showLabels | boolean | no | Specifies if labels in front of date and time parts should be rendered. |
71+
72+
Enum `TimeDisplayControlType`
73+
74+
| Name | Description |
75+
| ---- | ---- |
76+
| Text | Renders Time part as Masked Edit |
77+
| Dropdown | Renders Time part as Dropdown |
6378

6479
Enum `DateConvention`
6580

src/controls/dateTimePicker/DateTimePicker.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as telemetry from "../../common/telemetry";
1414
import { Async, css } from 'office-ui-fabric-react/lib/Utilities';
1515
import { IDateTimePickerProps, IDateTimePickerState, DateTimePickerStrings } from ".";
1616
import { TimeHelper } from "./TimeHelper";
17+
import { TimeDisplayControlType } from "./TimeDisplayControlType";
1718

1819
interface IDateComponents {
1920
day: Date;
@@ -201,7 +202,9 @@ export class DateTimePicker extends React.Component<IDateTimePickerProps, IDateT
201202
showSeconds = false,
202203
formatDate,
203204
value = this.state.day,
204-
strings: dateStrings = new DateTimePickerStrings() // Defines the DatePicker control labels
205+
strings: dateStrings = new DateTimePickerStrings(), // Defines the DatePicker control labels
206+
timeDisplayControlType,
207+
showLabels
205208
} = this.props;
206209

207210
const hours: number = value != null ? value.getHours() : this.state.hours;
@@ -214,14 +217,15 @@ export class DateTimePicker extends React.Component<IDateTimePickerProps, IDateT
214217
if (dateConvention === DateConvention.DateTime) {
215218
timeElm = (
216219
<div className={css(styles.row, styles.timeRow)}>
217-
<div className={styles.labelCell}><Label className={styles.fieldLabel}>{strings.DateTimePickerTime}</Label></div>
220+
{showLabels !== false && <div className={styles.labelCell}><Label className={styles.fieldLabel}>{strings.DateTimePickerTime}</Label></div>}
218221

219222
<div className={styles.time}>
220223
<div className={styles.picker}>
221224
<HoursComponent disabled={disabled}
222225
timeConvention={timeConvention}
223226
value={hours}
224-
onChange={this.dropdownHoursChanged} />
227+
onChange={this.dropdownHoursChanged}
228+
timeDisplayControlType={timeDisplayControlType || TimeDisplayControlType.Text} />
225229
</div>
226230

227231
<div className={styles.separator}>
@@ -231,7 +235,8 @@ export class DateTimePicker extends React.Component<IDateTimePickerProps, IDateT
231235
<div className={styles.picker}>
232236
<MinutesComponent disabled={disabled}
233237
value={minutes}
234-
onChange={this.dropdownMinutesChanged} />
238+
onChange={this.dropdownMinutesChanged}
239+
timeDisplayControlType={timeDisplayControlType || TimeDisplayControlType.Text} />
235240
</div>
236241

237242
{
@@ -247,7 +252,8 @@ export class DateTimePicker extends React.Component<IDateTimePickerProps, IDateT
247252
<div className={styles.picker}>
248253
<SecondsComponent disabled={disabled}
249254
value={seconds}
250-
onChange={this.dropdownSecondsChanged} />
255+
onChange={this.dropdownSecondsChanged}
256+
timeDisplayControlType={timeDisplayControlType || TimeDisplayControlType.Text} />
251257
</div>
252258
)
253259
}
@@ -264,9 +270,9 @@ export class DateTimePicker extends React.Component<IDateTimePickerProps, IDateT
264270

265271
<div className={styles.container}>
266272
<div className={styles.row}>
267-
<div className={styles.labelCell}>
273+
{showLabels !== false && <div className={styles.labelCell}>
268274
<Label className={styles.fieldLabel}>{strings.DateTimePickerDate}</Label>
269-
</div>
275+
</div>}
270276

271277
<div className={styles.picker}>
272278
<DatePicker

src/controls/dateTimePicker/HoursComponent.tsx

Lines changed: 114 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,126 @@ import { IHoursComponentProps } from './ITimeComponentProps';
44
import { TimeConvention } from './DateTimeConventions';
55
import { MaskedTextField } from 'office-ui-fabric-react/lib/TextField';
66
import { TimeHelper } from './TimeHelper';
7+
import { IDropdownOption, Dropdown } from 'office-ui-fabric-react/lib/Dropdown';
8+
import { TimeDisplayControlType } from './TimeDisplayControlType';
79

810
/**
911
* Hours component, this renders the hours dropdown
1012
*/
1113
export default class HoursComponent extends React.Component<IHoursComponentProps, {}> {
1214

15+
private _hours: IDropdownOption[];
16+
17+
constructor(props: IHoursComponentProps) {
18+
super(props);
19+
20+
this._initHoursOptions();
21+
}
22+
1323
public render(): JSX.Element {
14-
return (
15-
<MaskedTextField disabled={this.props.disabled}
16-
label=""
17-
value={this.props.value ? TimeHelper.hoursValue(this.props.value, this.props.timeConvention) : `${this.props.timeConvention === TimeConvention.Hours24 ? "00" : "12 AM"}`}
18-
mask={this.props.timeConvention === TimeConvention.Hours24 ? "29" : "19 AM"}
19-
maskFormat={{
20-
'1': /[0-1]/,
21-
'2': /[0-2]/,
22-
'9': /[0-9]/,
23-
'A': /[AaPp]/,
24-
'M': /[Mm]/
25-
}}
26-
onGetErrorMessage={(value) => {
27-
let message = "";
28-
const hours: number = parseInt(value);
29-
if (isNaN(hours)) {
30-
message = strings.DateTimePickerHourValueInvalid;
31-
}
32-
33-
if (!message && this.props.timeConvention === TimeConvention.Hours24) {
34-
message = hours > 23 ? strings.DateTimePickerHourValueInvalid : "";
35-
} else {
36-
message = hours > 12 ? strings.DateTimePickerHourValueInvalid : "";
37-
}
38-
39-
if (!message) {
40-
this.props.onChange(value);
41-
}
42-
43-
return message;
44-
}} />
45-
);
24+
const {
25+
disabled,
26+
timeConvention,
27+
value,
28+
timeDisplayControlType,
29+
onChange
30+
} = this.props;
31+
const renderDropdown = timeDisplayControlType === TimeDisplayControlType.Dropdown;
32+
if (renderDropdown) {
33+
return (
34+
<Dropdown
35+
disabled={this.props.disabled}
36+
label=''
37+
options={this._hours}
38+
onChanged={option => {
39+
onChange(option.text);
40+
}}
41+
dropdownWidth={110} />);
42+
}
43+
else {
44+
return (
45+
<MaskedTextField disabled={disabled}
46+
label=""
47+
value={value ? TimeHelper.hoursValue(value, timeConvention) : `${timeConvention === TimeConvention.Hours24 ? "00" : "12 AM"}`}
48+
mask={timeConvention === TimeConvention.Hours24 ? "29" : "19 AM"}
49+
maskFormat={{
50+
'1': /[0-1]/,
51+
'2': /[0-2]/,
52+
'9': /[0-9]/,
53+
'A': /[AaPp]/,
54+
'M': /[Mm]/
55+
}}
56+
onGetErrorMessage={(val) => {
57+
let message = "";
58+
const hours: number = parseInt(val);
59+
if (isNaN(hours)) {
60+
message = strings.DateTimePickerHourValueInvalid;
61+
}
62+
63+
if (!message && timeConvention === TimeConvention.Hours24) {
64+
message = hours > 23 ? strings.DateTimePickerHourValueInvalid : "";
65+
} else {
66+
message = hours > 12 ? strings.DateTimePickerHourValueInvalid : "";
67+
}
68+
69+
if (!message) {
70+
onChange(val);
71+
}
72+
73+
return message;
74+
}} />
75+
);
76+
}
77+
}
78+
79+
private _initHoursOptions() {
80+
const amDesignator = 'AM';
81+
const pmDesignator = 'PM';
82+
83+
const {
84+
value,
85+
timeConvention
86+
} = this.props;
87+
/*if (strings.AMDesignator) {
88+
amDesignator = ` ${strings.AMDesignator}`;
89+
}
90+
if (strings.PMDesignator) {
91+
pmDesignator = ` ${strings.PMDesignator}`;
92+
}*/
93+
94+
let hours: IDropdownOption[] = [];
95+
for (let i = 0; i < 24; i++) {
96+
let digit: string;
97+
if (this.props.timeConvention === TimeConvention.Hours24) {
98+
// 24 hours time convention
99+
if (i < 10) {
100+
digit = '0' + i;
101+
} else {
102+
digit = i.toString();
103+
}
104+
} else {
105+
// 12 hours time convention
106+
if (i === 0) {
107+
digit = `12${amDesignator}`;
108+
} else if (i < 12) {
109+
digit = `${i}${amDesignator}`;
110+
} else {
111+
if (i === 12) {
112+
digit = `12${pmDesignator}`;
113+
} else {
114+
digit = `${(i % 12)}${pmDesignator}`;
115+
}
116+
}
117+
}
118+
119+
let selected: boolean = false;
120+
if (i === value) {
121+
selected = true;
122+
}
123+
124+
hours.push({ key: i, text: digit, isSelected: selected });
125+
}
126+
127+
this._hours = hours;
46128
}
47129
}

src/controls/dateTimePicker/IDateTimePickerProps.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DayOfWeek } from 'office-ui-fabric-react/lib/utilities/dateValues/DateValues';
22
import { TimeConvention, DateConvention } from './DateTimeConventions';
33
import { IDateTimePickerStrings } from './IDateTimePickerStrings';
4+
import { TimeDisplayControlType } from './TimeDisplayControlType';
45

56
/**
67
* Public properties of the DateTimePicker custom field
@@ -91,4 +92,14 @@ export interface IDateTimePickerProps {
9192
* Specifies, if seconds dropdown should be shown, defaults to false.
9293
*/
9394
showSeconds?: boolean;
95+
96+
/**
97+
* Specifies what type of control to use when rendering time part.
98+
*/
99+
timeDisplayControlType?: TimeDisplayControlType;
100+
101+
/**
102+
* Specify if labels in front of date and time parts should be rendered. True by default
103+
*/
104+
showLabels?: boolean;
94105
}

src/controls/dateTimePicker/ITimeComponentProps.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';
22
import { TimeConvention } from './DateTimeConventions';
3+
import { TimeDisplayControlType } from './TimeDisplayControlType';
34

45
/**
56
* Time component properties interface
67
*/
78
export interface ITimeComponentProps {
89
disabled?: boolean;
910
value: number;
11+
timeDisplayControlType?: TimeDisplayControlType;
1012
onChange: (value?: string) => void;
1113
}
1214

0 commit comments

Comments
 (0)