mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 11:08:45 +08:00
feat(Input.Search): add loading prop (#18771)
* feat(Input.Search): add loading prop * fix: review change * optimize input search loading prop doc * fix: ci fail and onSearch disabled when loading
This commit is contained in:
parent
f659d23d22
commit
5cd01d0470
@ -11,7 +11,8 @@ export interface SearchProps extends InputProps {
|
||||
value: string,
|
||||
event?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLInputElement>,
|
||||
) => void;
|
||||
enterButton?: boolean | React.ReactNode;
|
||||
enterButton?: React.ReactNode;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export default class Search extends React.Component<SearchProps, any> {
|
||||
@ -26,7 +27,10 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
};
|
||||
|
||||
onSearch = (e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const { onSearch } = this.props;
|
||||
const { onSearch, loading } = this.props;
|
||||
|
||||
if (loading) return;
|
||||
|
||||
if (onSearch) {
|
||||
onSearch(this.input.input.value, e);
|
||||
}
|
||||
@ -41,8 +45,26 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
renderLoading = (prefixCls: string) => {
|
||||
const { enterButton, size } = this.props;
|
||||
|
||||
if (enterButton) {
|
||||
return (
|
||||
<Button className={`${prefixCls}-button`} type="primary" size={size} key="enterButton">
|
||||
<Icon type="loading" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return <Icon className={`${prefixCls}-icon`} type="loading" />;
|
||||
};
|
||||
|
||||
renderSuffix = (prefixCls: string) => {
|
||||
const { suffix, enterButton } = this.props;
|
||||
const { suffix, enterButton, loading } = this.props;
|
||||
|
||||
if (loading && !enterButton) {
|
||||
return [suffix, this.renderLoading(prefixCls)];
|
||||
}
|
||||
|
||||
if (enterButton) return suffix;
|
||||
|
||||
const node = (
|
||||
@ -68,10 +90,15 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
};
|
||||
|
||||
renderAddonAfter = (prefixCls: string) => {
|
||||
const { enterButton, size, disabled, addonAfter } = this.props;
|
||||
if (!enterButton) return addonAfter;
|
||||
const { enterButton, size, disabled, addonAfter, loading } = this.props;
|
||||
const btnClassName = `${prefixCls}-button`;
|
||||
|
||||
if (loading && enterButton) {
|
||||
return [this.renderLoading(prefixCls), addonAfter];
|
||||
}
|
||||
|
||||
if (!enterButton) return addonAfter;
|
||||
|
||||
let button: React.ReactNode;
|
||||
const enterButtonAsElement = enterButton as React.ReactElement<any>;
|
||||
if (enterButtonAsElement.type === Button || enterButtonAsElement.type === 'button') {
|
||||
|
@ -137,4 +137,11 @@ describe('Input.Search', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support loading', () => {
|
||||
const wrapper = mount(<Search loading />);
|
||||
const wrapperWithEnterButton = mount(<Search loading enterButton />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -150,3 +150,82 @@ exports[`Input.Search should support custom button 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support loading 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading ant-input-search-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support loading 2`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
@ -1811,6 +1811,169 @@ exports[`renders ./components/input/demo/search-input.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/input/demo/search-input-loading.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading deault"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading ant-input-search-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading with suffix"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading ant-input-search-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading with enterButton"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading with enterButton and addonAfter"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: loading"
|
||||
class="anticon anticon-loading"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
addonAfter
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/input/demo/size.md correctly 1`] = `
|
||||
<div
|
||||
class="example-input"
|
||||
|
41
components/input/demo/search-input-loading.md
Normal file
41
components/input/demo/search-input-loading.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 搜索框 loading
|
||||
en-US: Search box with loading
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
用于 `onSearch` 的时候展示 `loading`。
|
||||
|
||||
## en-US
|
||||
|
||||
Search loading when onSearch.
|
||||
|
||||
```jsx
|
||||
import { Input } from 'antd';
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Search placeholder="input search loading deault" loading />
|
||||
<br />
|
||||
<br />
|
||||
<Search placeholder="input search loading with suffix" loading suffix="suffix" />
|
||||
<br />
|
||||
<br />
|
||||
<Search placeholder="input search loading with enterButton" loading enterButton />
|
||||
<br />
|
||||
<br />
|
||||
<Search
|
||||
placeholder="input search loading with enterButton and addonAfter"
|
||||
loading
|
||||
enterButton
|
||||
addonAfter="addonAfter"
|
||||
/>
|
||||
</div>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
@ -56,6 +56,7 @@ The rest of the props of `Input.TextArea` are the same as the original [textarea
|
||||
| --- | --- | --- | --- | --- |
|
||||
| enterButton | to show an enter button after input. This prop is conflict with addon. | boolean\|ReactNode | false | |
|
||||
| onSearch | The callback function that is triggered when you click on the search-icon or press Enter key. | function(value, event) | | |
|
||||
| loading | Search box with loading. | boolean | | |
|
||||
|
||||
Supports all props of `Input`.
|
||||
|
||||
|
@ -55,6 +55,7 @@ Input 的其他属性和 React 自带的 [input](https://facebook.github.io/reac
|
||||
| --- | --- | --- | --- | --- |
|
||||
| enterButton | 是否有确认按钮,可设为按钮文字。该属性会与 addon 冲突。 | boolean\|ReactNode | false | |
|
||||
| onSearch | 点击搜索或按下回车键时的回调 | function(value, event) | | |
|
||||
| loading | 搜索 loading | boolean | | |
|
||||
|
||||
其余属性和 Input 一致。
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
border: 0;
|
||||
|
||||
.@{search-prefix}-button {
|
||||
width: 100%;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -491,7 +491,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
@ -509,7 +509,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
@ -671,7 +671,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
@ -771,7 +771,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class=""
|
||||
class="ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
@ -789,7 +789,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
class="ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
@ -838,7 +838,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class=""
|
||||
class="ant-table-row-cell-break-word"
|
||||
>
|
||||
<span
|
||||
class="ant-table-header-column"
|
||||
|
Loading…
Reference in New Issue
Block a user