Skip to content

Commit

Permalink
fix(DatePicker,DateRangePicker): fix the issue that renderValue doe…
Browse files Browse the repository at this point in the history
…s not work (#3798)
  • Loading branch information
simonguo committed May 15, 2024
1 parent 0da17e9 commit 494c9c6
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 245 deletions.
128 changes: 67 additions & 61 deletions docs/pages/components/date-picker/en-US/index.md

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions docs/pages/components/date-picker/fragments/render-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--start-code-->

```js
import { DatePicker } from 'rsuite';
import format from 'date-fns/format';

const App = () => {
return (
<DatePicker
editable={false}
placeholder="Select Date"
renderValue={value => {
return format(value, 'EEE, d MMM');
}}
/>
);
};

ReactDOM.render(<App />, document.getElementById('root'));
```

<!--end-code-->
2 changes: 2 additions & 0 deletions docs/pages/components/date-picker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { DatePicker, Button, InputGroup, Input, Stack } from 'rsuite';
import format from 'date-fns/format';
import addDays from 'date-fns/addDays';
import subDays from 'date-fns/subDays';
import isBefore from 'date-fns/isBefore';
Expand Down Expand Up @@ -28,6 +29,7 @@ export default function Page() {
InputGroup,
Input,
Stack,
format,
addDays,
subDays,
isBefore,
Expand Down
130 changes: 68 additions & 62 deletions docs/pages/components/date-picker/zh-CN/index.md

Large diffs are not rendered by default.

106 changes: 57 additions & 49 deletions docs/pages/components/date-range-picker/en-US/index.md

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions docs/pages/components/date-range-picker/fragments/render-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--start-code-->

```js
import { DateRangePicker } from 'rsuite';
import format from 'date-fns/format';

const App = () => {
return (
<DateRangePicker
editable={false}
placeholder="Select Date"
renderValue={([start, end]) => {
return format(start, 'EEE, d MMM') + ' - ' + format(end, 'EEE, d MMM');
}}
/>
);
};

ReactDOM.render(<App />, document.getElementById('root'));
```

<!--end-code-->
2 changes: 2 additions & 0 deletions docs/pages/components/date-range-picker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import endOfMonth from 'date-fns/endOfMonth';
import subDays from 'date-fns/subDays';
import isAfter from 'date-fns/isAfter';
import addMonths from 'date-fns/addMonths';
import format from 'date-fns/format';
import { BsCalendar2MonthFill } from 'react-icons/bs';
import {
FaCalendar,
Expand All @@ -32,6 +33,7 @@ export default function Page() {
DateRangePicker,
Button,
Divider,
format,
addDays,
subDays,
isAfter,
Expand Down
114 changes: 58 additions & 56 deletions docs/pages/components/date-range-picker/zh-CN/index.md

Large diffs are not rendered by default.

32 changes: 27 additions & 5 deletions src/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
onMenuKeyDown
} from '../internals/Picker';
import { OverlayCloseCause } from '../internals/Overlay/OverlayTrigger';
import Input from '../Input';
import DateInput from '../DateInput';
import InputGroup from '../InputGroup';
import { splitRanges, deprecatedPropTypes, getRestProps } from './utils';
Expand Down Expand Up @@ -172,6 +173,11 @@ export interface DatePickerProps
/** Called when clean */
onClean?: (event: React.MouseEvent) => void;

/**
* Custom rendering of the selected date.
*/
renderValue?: (value: Date, format: string) => string;

/**
* Custom rendering calendar cell content.
*
Expand All @@ -196,7 +202,7 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
editable = true,
defaultValue,
disabled,
readOnly,
readOnly: readOnly,
plaintext,
// todo Not consistent with locale.formatDayPattern
format: formatStr = 'yyyy-MM-dd',
Expand Down Expand Up @@ -237,6 +243,7 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
onToggleTimeDropdown,
onShortcutClick,
renderCell,
renderValue,
disabledDate: DEPRECATED_disabledDate,
disabledHours: DEPRECATED_disabledHours,
disabledMinutes: DEPRECATED_disabledMinutes,
Expand Down Expand Up @@ -613,6 +620,21 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
const [ariaProps, rest] = partitionHTMLProps(restProps, { htmlProps: [], includeAria: true });
const invalidValue = value && isErrorValue(value);

// Custom rendering of the selected value
let customValue: string | null = null;

// Input box is read-only when the component is uneditable or loading state
let inputReadOnly: boolean = readOnly || !editable || loading || false;

if (typeof renderValue === 'function' && value) {
customValue = renderValue(value, formatStr);

// If the custom rendering value, the input box is read-only
inputReadOnly = true;
}

const TargetInput = customValue ? Input : DateInput;

return (
<PickerToggleTrigger
trigger="active"
Expand Down Expand Up @@ -641,22 +663,22 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
<PickerLabel className={prefix`label`} id={`${id}-label`}>
{label}
</PickerLabel>
<DateInput
<TargetInput
aria-haspopup="dialog"
aria-invalid={invalidValue}
aria-labelledby={label ? `${id}-label` : undefined}
{...(ariaProps as any)}
ref={target}
id={id}
value={value}
value={customValue || value}
format={formatStr}
placeholder={placeholder ? placeholder : formatStr}
disabled={disabled}
onChange={handleInputChange}
readOnly={readOnly || !editable || loading}
plaintext={plaintext}
readOnly={inputReadOnly}
onKeyDown={handleInputKeyDown}
/>

<PickerIndicator
loading={loading}
caretAs={caretAs}
Expand Down
11 changes: 11 additions & 0 deletions src/DatePicker/test/DatePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ describe('DatePicker', () => {
expect(screen.getByRole('textbox')).to.have.value('2017-08-14');
});

it('Should render a custom value', () => {
render(
<DatePicker
defaultValue={new Date('2024-05-13')}
renderValue={value => format(value, 'EEE, d MMM')}
/>
);

expect(screen.getByRole('textbox')).to.have.value('Mon, 13 May');
});

it('Should open a dialog containing grid view of dates in a month', () => {
render(<DatePicker defaultOpen defaultValue={new Date('2023-10-01')} />);
expect(screen.getByRole('dialog')).to.be.visible;
Expand Down
5 changes: 0 additions & 5 deletions src/DatePicker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,4 @@ export interface DeprecatedProps {
* @deprecated Use {@link shouldDisableSecond} instead
*/
disabledSeconds?: (second: number, date: Date) => boolean;

/**
* @deprecated
*/
renderValue?: (value: Date, format: string) => string;
}
32 changes: 25 additions & 7 deletions src/DateRangePicker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { getSafeCalendarDate, getMonthHoverRange, getWeekHoverRange, isSameRange
import { deprecatePropTypeNew, oneOf } from '../internals/propTypes';
import DateRangePickerContext from './DateRangePickerContext';
import DateRangeInput from '../DateRangeInput';
import Input from '../Input';
import InputGroup from '../InputGroup';
import Header from './Header';

Expand Down Expand Up @@ -165,12 +166,13 @@ export interface DateRangePickerProps
onClean?: (event: React.MouseEvent) => void;

/**
* Custom render value
* @deprecated
* Custom rendering of the selected date range.
*/
renderValue?: (value: DateRange, format: string) => React.ReactNode;
renderValue?: (value: DateRange, format: string) => string;

/** Custom render for calendar title */
/**
* Custom render for calendar title
*/
renderTitle?: (date: Date) => React.ReactNode;
}

Expand Down Expand Up @@ -253,6 +255,7 @@ const DateRangePicker = React.forwardRef((props: DateRangePickerProps, ref) => {
onSelect,
onShortcutClick,
renderTitle,
renderValue,
...restProps
} = props;

Expand Down Expand Up @@ -916,6 +919,21 @@ const DateRangePicker = React.forwardRef((props: DateRangePickerProps, ref) => {
const showCleanButton = cleanable && hasValue && !readOnly;
const invalidValue = value && isErrorValue(value);

// Custom rendering of the selected value
let customValue: string | null = null;

// Input box is read-only when the component is uneditable or loading state
let inputReadOnly: boolean = readOnly || !editable || loading || false;

if (typeof renderValue === 'function' && value) {
customValue = renderValue(value, formatStr);

// If the custom rendering value, the input box is read-only
inputReadOnly = true;
}

const TargetInput = customValue ? Input : DateRangeInput;

return (
<PickerToggleTrigger
trigger="active"
Expand Down Expand Up @@ -947,19 +965,19 @@ const DateRangePicker = React.forwardRef((props: DateRangePickerProps, ref) => {
<PickerLabel className={prefix`label`} id={`${id}-label`}>
{label}
</PickerLabel>
<DateRangeInput
<TargetInput
aria-haspopup="dialog"
aria-invalid={invalidValue}
aria-labelledby={label ? `${id}-label` : undefined}
{...(ariaProps as any)}
ref={target}
id={id}
value={value}
value={customValue || value}
character={character}
format={formatStr}
placeholder={placeholder ? placeholder : rangeFormatStr}
disabled={disabled}
readOnly={readOnly || !editable || loading}
readOnly={inputReadOnly}
plaintext={plaintext}
htmlSize={getInputHtmlSize()}
onChange={handleInputChange}
Expand Down
13 changes: 13 additions & 0 deletions src/DateRangePicker/test/DateRangePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ describe('DateRangePicker', () => {
expect(screen.getByRole('textbox')).to.have.value('11/11/2019 01:00:00 ~ 11/12/2019 01:00:00');
});

it('Should render a custom value', () => {
render(
<DateRangePicker
defaultValue={[new Date('2024-05-13'), new Date('2024-05-14')]}
renderValue={([start, end]) => {
return format(start, 'EEE, d MMM') + ' ~ ' + format(end, 'EEE, d MMM');
}}
/>
);

expect(screen.getByRole('textbox')).to.have.value('Mon, 13 May ~ Tue, 14 May');
});

it('Should select date time successfully', () => {
const defaultValue = [new Date(2019, 10, 11, 0, 0, 0), new Date(2019, 11, 11, 0, 0, 0)] as [
Date,
Expand Down

0 comments on commit 494c9c6

Please sign in to comment.