Skip to content

Clear datepicker with null #3169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
18 changes: 18 additions & 0 deletions components/component-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5771,6 +5771,17 @@
"computed": false
}
},
"disabledSelection": {
"type": {
"name": "array"
},
"required": false,
"description": "An array of objects of rows that selection is disabled. See `items` prop for shape of objects.",
"defaultValue": {
"value": "[]",
"computed": false
}
},
"selectRows": {
"type": {
"name": "union",
Expand Down Expand Up @@ -6309,6 +6320,13 @@
"params": [],
"returns": null
},
{
"name": "handleResetDate",
"docblock": null,
"modifiers": [],
"params": [],
"returns": null
},
{
"name": "openDialogFromIcon",
"docblock": null,
Expand Down
4 changes: 3 additions & 1 deletion components/date-picker/__docs__/storybook-stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import CustomInput from '../__examples__/custom-input';
import SnaphotDefault from '../__examples__/snapshot-default';
import WeekdayPicker from '../__examples__/weekday-picker';
import ErrorPicker from '../__examples__/error-picker';
import Clearable from '../__examples__/clearable';

// eslint-disable-next-line camelcase
import UNSAFE_DirectionSettings from '../../utilities/UNSAFE_direction';
Expand Down Expand Up @@ -52,4 +53,5 @@ storiesOf(DATE_PICKER, module)
))
.add('DOM Snapshot', () => <SnaphotDefault />)
.add('Weekday picker', () => <WeekdayPicker />)
.add('Error', () => <ErrorPicker />);
.add('Error', () => <ErrorPicker />)
.add('Clearable', () => <Clearable action={action} />);
71 changes: 71 additions & 0 deletions components/date-picker/__examples__/clearable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable no-console, react/prop-types */
import React from 'react';
import moment from 'moment';

import IconSettings from '~/components/icon-settings';
import Datepicker from '~/components/date-picker';
import Button from '~/components/button';

class Example extends React.Component {
static displayName = 'DatepickerExample';

constructor() {
super();
this.state = {
value: undefined,
};
}

handleChange = (event, data) => {
this.setState({ value: data.date });
};

render() {
return (
<IconSettings iconPath="/assets/icons">
<Datepicker
labels={{
label: 'Date',
}}
onChange={(event, data) => {
this.handleChange(event, data);

if (this.props.action) {
const dataAsArray = Object.keys(data).map((key) => data[key]);
this.props.action('onChange')(event, data, ...dataAsArray);
} else if (console) {
console.log('onChange', event, data);
}
}}
onCalendarFocus={(event, data) => {
if (this.props.action) {
const dataAsArray = Object.keys(data).map((key) => data[key]);
this.props.action('onCalendarFocus')(event, data, ...dataAsArray);
} else if (console) {
console.log('onCalendarFocus', event, data);
}
}}
formatter={(date) => {
return date ? moment(date).format('M/D/YYYY') : '';
}}
parser={(dateString) => {
return moment(dateString, 'MM-DD-YYYY').toDate();
}}
value={this.state.value}
/>
<Button
assistiveText="Clear date"
iconCategory="utility"
iconName="clear"
style={{ marginLeft: '.5rem' }}
variant="icon"
onClick={() => {
this.setState({ value: null });
}}
/>
</IconSettings>
);
}
}

export default Example; // export is replaced with `ReactDOM.render(<Example />, mountNode);` at runtime
24 changes: 24 additions & 0 deletions components/date-picker/__tests__/date-picker.browser-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,28 @@ describe('SLDSDatepicker', function describeFunction() {
trigger.simulate('click', {});
});
});

describe('Clearing controlled input', () => {
afterEach(() => wrapper.unmount());

it('clears input on null value', () => {
wrapper = mount(<DemoComponent value={new Date()} />);

const input = wrapper.find('input');
expect(input).not.to.have.value('');

wrapper.setProps({ value: null });
expect(input).to.have.value('');
});

it('does not clear input on non-null value', () => {
wrapper = mount(<DemoComponent value={new Date()} />);

const input = wrapper.find('input');
expect(input).not.to.have.value('');

wrapper.setProps({ value: undefined });
expect(input).not.to.have.value('');
});
});
});
2 changes: 1 addition & 1 deletion components/date-picker/date-picker.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ declare module '@salesforce/design-system-react/components/date-picker/date-pick
/**
* Sets date with a `Date` ECMAScript object. _Tested with snapshot testing._
*/
value?: Date;
value?: Date | null;
};
/**
* A date picker is a non-text input form element. You can select a single date from a popup calendar. Please use an external library such as [MomentJS](https://github.com/moment/moment/) for date formatting and parsing and internationalization. You will want to use your date library within the `parser` and `formatter` callbacks.
Expand Down
15 changes: 15 additions & 0 deletions components/date-picker/date-picker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,13 @@ class Datepicker extends React.Component {
checkProps(DATE_PICKER, props, componentDoc);
}

componentDidUpdate(prevProps) {
// clear controlled input when value is set to null
if (this.props.value === null && prevProps.value !== this.props.value) {
this.handleResetDate();
}
}

getDatePicker = ({ labels, assistiveText }) => {
let date;
// Use props if present. Otherwise, use state.
Expand Down Expand Up @@ -572,6 +579,14 @@ class Datepicker extends React.Component {
}
};

handleResetDate = () => {
this.setState({
value: undefined,
formattedValue: '',
inputValue: '',
});
};

openDialogFromIcon = () => {
this.setState({ isOpenFromIcon: true });
this.openDialog(true);
Expand Down