diff --git a/__tests__/renderers/Form/__snapshots__/datetime.test.tsx.snap b/__tests__/renderers/Form/__snapshots__/datetime.test.tsx.snap index 46239e57d..4575d1916 100644 --- a/__tests__/renderers/Form/__snapshots__/datetime.test.tsx.snap +++ b/__tests__/renderers/Form/__snapshots__/datetime.test.tsx.snap @@ -56,11 +56,12 @@ exports[`Renderer:date 1`] = ` class="cxd-DatePicker" tabindex="0" > - - 2019-06-06 21:11:00 - + diff --git a/__tests__/renderers/Form/__snapshots__/inputDate.test.tsx.snap b/__tests__/renderers/Form/__snapshots__/inputDate.test.tsx.snap index 723b7f43f..e29b39f60 100644 --- a/__tests__/renderers/Form/__snapshots__/inputDate.test.tsx.snap +++ b/__tests__/renderers/Form/__snapshots__/inputDate.test.tsx.snap @@ -56,11 +56,12 @@ exports[`Renderer:inputDate 1`] = ` class="cxd-DatePicker" tabindex="0" > - - 2019-06-07 - + diff --git a/__tests__/renderers/Form/datetime.test.tsx b/__tests__/renderers/Form/datetime.test.tsx index f03a30c9a..496a555d5 100644 --- a/__tests__/renderers/Form/datetime.test.tsx +++ b/__tests__/renderers/Form/datetime.test.tsx @@ -31,8 +31,11 @@ test('Renderer:date', async () => { ) ); - const input = container.querySelector('.cxd-DatePicker-value'); - expect(input?.innerHTML).toEqual( + const input = container.querySelector( + '.cxd-DatePicker input' + )! as HTMLInputElement; + + expect(input.value).toEqual( moment(1559826660, 'X').format('YYYY-MM-DD HH:mm:ss') ); diff --git a/__tests__/renderers/Form/inputDate.test.tsx b/__tests__/renderers/Form/inputDate.test.tsx index 0d983da39..4582af62b 100644 --- a/__tests__/renderers/Form/inputDate.test.tsx +++ b/__tests__/renderers/Form/inputDate.test.tsx @@ -31,10 +31,10 @@ test('Renderer:inputDate', async () => { ) ); - const input = container.querySelector('.cxd-DatePicker-value'); - expect(input?.innerHTML).toEqual( - moment(1559836800, 'X').format('YYYY-MM-DD') - ); + const input = container.querySelector( + '.cxd-DatePicker input' + )! as HTMLInputElement; + expect(input.value).toEqual(moment(1559836800, 'X').format('YYYY-MM-DD')); expect(container).toMatchSnapshot(); }); diff --git a/__tests__/renderers/Form/inputMonth.test.tsx b/__tests__/renderers/Form/inputMonth.test.tsx index ccbbf48d5..09de307bc 100644 --- a/__tests__/renderers/Form/inputMonth.test.tsx +++ b/__tests__/renderers/Form/inputMonth.test.tsx @@ -8,27 +8,28 @@ import {makeEnv} from '../../helper'; import moment from 'moment'; test('Renderer:inputMonth click', async () => { - const {container, findByText} = render( - amisRender( - { - type: 'form', - api: '/api/xxx', - body: [ - { - type: 'input-month', - name: 'month', - label: '时间' - } - ], - title: 'The form', - actions: [] - }, - {}, - makeEnv({}) - ) - ); + const {container, findByText, findByPlaceholderText, findByDisplayValue} = + render( + amisRender( + { + type: 'form', + api: '/api/xxx', + body: [ + { + type: 'input-month', + name: 'month', + label: '时间' + } + ], + title: 'The form', + actions: [] + }, + {}, + makeEnv({}) + ) + ); - const inputDate = await findByText('请选择月份'); + const inputDate = await findByPlaceholderText('请选择月份'); fireEvent.click(inputDate); @@ -43,11 +44,11 @@ test('Renderer:inputMonth click', async () => { const lastYearMonth = moment().subtract(1, 'year').format('YYYY') + '-01'; - await findByText(lastYearMonth); + await findByDisplayValue(lastYearMonth); const value = document.querySelector( - '.cxd-DatePicker-value' - ) as HTMLSpanElement; + '.cxd-DatePicker input' + ) as HTMLInputElement; - expect(value.innerHTML).toEqual(lastYearMonth); + expect(value.value).toEqual(lastYearMonth); }); diff --git a/__tests__/renderers/Form/inputYear.test.tsx b/__tests__/renderers/Form/inputYear.test.tsx index 8da3f5e8e..9e617a54b 100644 --- a/__tests__/renderers/Form/inputYear.test.tsx +++ b/__tests__/renderers/Form/inputYear.test.tsx @@ -8,7 +8,7 @@ import {makeEnv} from '../../helper'; import moment from 'moment'; test('Renderer:inputYear click', async () => { - const {container, findByText} = render( + const {container, findByPlaceholderText, findByText} = render( amisRender( { type: 'form', @@ -28,7 +28,7 @@ test('Renderer:inputYear click', async () => { ) ); - const inputDate = await findByText('请选择年'); + const inputDate = await findByPlaceholderText('请选择年'); fireEvent.click(inputDate); @@ -39,8 +39,8 @@ test('Renderer:inputYear click', async () => { fireEvent.click(thisYear); const value = document.querySelector( - '.cxd-DatePicker-value' - ) as HTMLSpanElement; + '.cxd-DatePicker input' + ) as HTMLInputElement; - expect(value.innerHTML).toEqual(thisYearText); + expect(value.value).toEqual(thisYearText); }); diff --git a/__tests__/renderers/Form/mobileInputDate.test.tsx b/__tests__/renderers/Form/mobileInputDate.test.tsx index c3103bcbc..e10298f70 100644 --- a/__tests__/renderers/Form/mobileInputDate.test.tsx +++ b/__tests__/renderers/Form/mobileInputDate.test.tsx @@ -17,7 +17,7 @@ afterAll(() => { }); test('Renderer:mobile Input Date', async () => { - const {container, findByText, getByText} = render( + const {container, findByPlaceholderText, getByText} = render( amisRender( { type: 'form', @@ -35,7 +35,7 @@ test('Renderer:mobile Input Date', async () => { ) ); - const inputDate = await findByText('请选择日期'); + const inputDate = await findByPlaceholderText('请选择日期'); fireEvent.click(inputDate); const confirmButton = document.querySelector( @@ -44,9 +44,9 @@ test('Renderer:mobile Input Date', async () => { fireEvent.click(confirmButton); - const value = document.querySelector( - '.cxd-DatePicker-value' - ) as HTMLSpanElement; + // const value = document.querySelector( + // '.cxd-DatePicker-value' + // ) as HTMLSpanElement; // TODO: 这里原组件的日错了,等修复 // expect(value.innerHTML).toEqual(moment().format('YYYY-MM-DD')); diff --git a/docs/zh-CN/components/form/switch.md b/docs/zh-CN/components/form/switch.md index 2d78cf9dd..5e84634a5 100755 --- a/docs/zh-CN/components/form/switch.md +++ b/docs/zh-CN/components/form/switch.md @@ -84,20 +84,39 @@ order: 51 } ``` +## 默认值 + +和其它表单项一样,如果要设置默认值,可以使用 value 属性 + +```schema: scope="body" +{ + "type": "form", + "debug": true, + "body": [ + { + "name": "switch", + "type": "switch", + "label": "开关", + "value": false + } + ] +} +``` + ## 属性表 除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置 -| 属性名 | 类型 | 默认值 | 说明 | -| ---------- | -------- | --------- | ------------ | -| option | `string` | | 选项说明 | -| onText | `string / IconSchema` | | 开启时开关显示的内容 | -| offText | `string / IconSchema` | | 关闭时开关显示的内容 | -| trueValue | `boolean / string / number` | `true` | 标识真值 | -| falseValue | `boolean / string / number` | `false` | 标识假值 | +| 属性名 | 类型 | 默认值 | 说明 | +| ---------- | --------------------------- | ------- | -------------------- | +| option | `string` | | 选项说明 | +| onText | `string / IconSchema` | | 开启时开关显示的内容 | +| offText | `string / IconSchema` | | 关闭时开关显示的内容 | +| trueValue | `boolean / string / number` | `true` | 标识真值 | +| falseValue | `boolean / string / number` | `false` | 标识假值 | IconSchema 配置 -| 属性名 | 类型 | 默认值 | 说明 | +| 属性名 | 类型 | 默认值 | 说明 | | ---------- | -------- | --------- | ------------ | -| type | `string` | | `icon` | -| icon | `string` | | icon的类型 | +| type | `string` | | `icon` | +| icon | `string` | | icon 的类型 | diff --git a/scss/components/form/_date.scss b/scss/components/form/_date.scss index 4e5e2c809..b8f3948e6 100644 --- a/scss/components/form/_date.scss +++ b/scss/components/form/_date.scss @@ -12,6 +12,19 @@ background: var(--DatePicker-bg); border-radius: var(--DatePicker-borderRadius); + input { + display: inline-block; + width: 100%; + background: none; + padding: 0; + border: 0; + &:focus { + border: none; + outline: none; + box-sizing: none; + } + } + @include input-border(); &:not(.is-disabled) { diff --git a/src/components/DatePicker.tsx b/src/components/DatePicker.tsx index 168c0f904..56217d417 100644 --- a/src/components/DatePicker.tsx +++ b/src/components/DatePicker.tsx @@ -17,6 +17,7 @@ import Calendar from './calendar/Calendar'; import {localeable, LocaleProps, TranslateFn} from '../locale'; import {isMobile, ucFirst} from '../utils/helper'; import CalendarMobile from './CalendarMobile'; +import Input from './Input'; const availableShortcuts: {[propName: string]: any} = { now: { @@ -302,6 +303,7 @@ export interface DatePickerState { isOpened: boolean; isFocused: boolean; value: moment.Moment | undefined; + inputValue: string | undefined; // 手动输入的值 } function normalizeValue(value: any, format?: string) { @@ -329,11 +331,15 @@ export class DatePicker extends React.Component { state: DatePickerState = { isOpened: false, isFocused: false, - value: normalizeValue(this.props.value, this.props.format) + value: normalizeValue(this.props.value, this.props.format), + inputValue: + normalizeValue(this.props.value, this.props.format)?.format( + this.props.inputFormat + ) || '' }; constructor(props: DateProps) { super(props); - + this.inputRef = React.createRef(); this.handleChange = this.handleChange.bind(this); this.selectRannge = this.selectRannge.bind(this); this.checkIsValidDate = this.checkIsValidDate.bind(this); @@ -348,10 +354,13 @@ export class DatePicker extends React.Component { this.getTarget = this.getTarget.bind(this); this.handlePopOverClick = this.handlePopOverClick.bind(this); this.renderShortCuts = this.renderShortCuts.bind(this); + this.inputChange = this.inputChange.bind(this); } dom: HTMLDivElement; + inputRef: React.RefObject; + componentDidUpdate(prevProps: DateProps) { const props = this.props; @@ -403,13 +412,17 @@ export class DatePicker extends React.Component { } open(fn?: () => void) { - this.props.disabled || - this.setState( - { - isOpened: true - }, - fn - ); + if (this.props.disabled) { + return; + } + this.setState( + { + isOpened: true + }, + fn + ); + const input = this.inputRef.current; + input && input.focus(); } close() { @@ -423,6 +436,7 @@ export class DatePicker extends React.Component { e.stopPropagation(); const onChange = this.props.onChange; onChange(''); + this.setState({inputValue: ''}); } handleChange(value: moment.Moment) { @@ -432,6 +446,7 @@ export class DatePicker extends React.Component { minDate, maxDate, dateFormat, + inputFormat, timeFormat, closeOnSelect, utc, @@ -453,6 +468,31 @@ export class DatePicker extends React.Component { if (closeOnSelect && dateFormat && !timeFormat) { this.close(); } + + this.setState({ + inputValue: utc + ? moment.utc(value).format(inputFormat) + : value.format(inputFormat) + }); + } + + // 手动输入日期 + inputChange(e: React.ChangeEvent) { + const {onChange, inputFormat, format, utc} = this.props; + const value = e.currentTarget.value; + this.setState({inputValue: value}); + if (value === '') { + onChange(''); + } else { + const newDate = moment(value, inputFormat); + const dateValue = utc + ? moment.utc(newDate).format(format) + : newDate.format(format); + // 小于 0 的日期丢弃 + if (!dateValue.startsWith('-')) { + onChange(dateValue); + } + } } selectRannge(item: any) { @@ -693,15 +733,13 @@ export class DatePicker extends React.Component { ref={this.domRef} onClick={this.handleClick} > - {date ? ( - - {date.format(inputFormat)} - - ) : ( - - {__(placeholder)} - - )} + {clearable && !disabled && normalizeValue(value, format) ? ( diff --git a/src/components/calendar/Calendar.tsx b/src/components/calendar/Calendar.tsx index b9e5d7cb5..734a57643 100644 --- a/src/components/calendar/Calendar.tsx +++ b/src/components/calendar/Calendar.tsx @@ -161,18 +161,19 @@ class BaseDatePicker extends React.Component< updatedState = this.getStateFromProps(props); } - if (updatedState.open === undefined) { - if (typeof props.open !== 'undefined') { - updatedState.open = props.open; - } else if ( - prevProps.closeOnSelect && - this.state.currentView !== viewModes.TIME - ) { - updatedState.open = false; - } else { - updatedState.open = this.state.open; - } - } + // open 是外部控制了 + // if (updatedState.open === undefined) { + // if (typeof props.open !== 'undefined') { + // updatedState.open = props.open; + // } else if ( + // prevProps.closeOnSelect && + // this.state.currentView !== viewModes.TIME + // ) { + // updatedState.open = false; + // } else { + // updatedState.open = this.state.open; + // } + // } if (props.viewMode !== prevProps.viewMode) { updatedState.currentView = props.viewMode; @@ -236,6 +237,10 @@ class BaseDatePicker extends React.Component< updatedState.viewDate = moment(props.viewDate); } + if (Object.keys(updatedState).length) { + this.setState(updatedState); + } + this.checkTZ(props); }