Skip to content

Commit

Permalink
feat: Add loading prop for Input.Search, close #14538
Browse files Browse the repository at this point in the history
  • Loading branch information
dengfuping committed Feb 8, 2019
1 parent d1fde36 commit de250cd
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 34 deletions.
39 changes: 32 additions & 7 deletions components/input/Search.tsx
Expand Up @@ -5,13 +5,16 @@ import Icon from '../icon';
import Button from '../button';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';

function noop() {}

export interface SearchProps extends InputProps {
inputPrefixCls?: string;
onSearch?: (
value: string,
event?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLInputElement>,
) => any;
enterButton?: boolean | React.ReactNode;
loading?: boolean;
}

export default class Search extends React.Component<SearchProps, any> {
Expand Down Expand Up @@ -42,36 +45,57 @@ export default class Search extends React.Component<SearchProps, any> {
};

getButtonOrIcon(prefixCls: string) {
const { enterButton, size, disabled } = this.props;
const { enterButton, size, disabled, loading } = this.props;
const enterButtonAsElement = enterButton as React.ReactElement<any>;
const iconClassName = classNames(`${prefixCls}-icon`, {
[`${prefixCls}-loading`]: !!loading,
});
const buttonClassName = classNames(`${prefixCls}-button`, {
[`${prefixCls}-loading`]: !!loading,
});
let node;
if (!enterButton) {
node = <Icon className={`${prefixCls}-icon`} type="search" key="searchIcon" />;
node = (
<Icon className={iconClassName} type={loading ? 'loading' : 'search'} key="searchIcon" />
);
} else if (enterButtonAsElement.type === Button || enterButtonAsElement.type === 'button') {
node = React.cloneElement(
enterButtonAsElement,
enterButtonAsElement.type === Button
? {
className: `${prefixCls}-button`,
className: buttonClassName,
size,
}
: {},
);
} else {
node = (
<Button
className={`${prefixCls}-button`}
className={buttonClassName}
type="primary"
size={size}
disabled={disabled}
key="enterButton"
>
{enterButton === true ? <Icon type="search" /> : enterButton}
{enterButton === true ? (
<Icon type={loading ? 'loading' : 'search'} />
) : (
<span>
<span
className={classNames({
[`${prefixCls}-button-text-loading`]: !!loading,
})}
>
{enterButton}
</span>
{loading && <Icon type="loading" />}
</span>
)}
</Button>
);
}
return React.cloneElement(node, {
onClick: this.onSearch,
onClick: loading ? noop : this.onSearch,
});
}

Expand All @@ -83,6 +107,7 @@ export default class Search extends React.Component<SearchProps, any> {
size,
suffix,
enterButton,
loading,
...others
} = this.props;
delete (others as any).onSearch;
Expand All @@ -104,7 +129,7 @@ export default class Search extends React.Component<SearchProps, any> {
});
return (
<Input
onPressEnter={this.onSearch}
onPressEnter={loading ? noop : this.onSearch}
{...others}
size={size}
className={inputClassName}
Expand Down
13 changes: 13 additions & 0 deletions components/input/__tests__/Search.test.js
Expand Up @@ -126,4 +126,17 @@ describe('Input.Search', () => {
}),
);
});

it('should be loading when loading is true', async () => {
let loading = false;
const wrapper = mount(<Search loading={loading} />);
expect(wrapper.find('.anticon-loading')).toHaveLength(0);

loading = true;
wrapper.setProps({ loading });

await new Promise(resolve => setTimeout(resolve, 500));
wrapper.update();
expect(wrapper.find('.anticon-loading')).toHaveLength(1);
});
});
77 changes: 52 additions & 25 deletions components/input/demo/search-input.md
Expand Up @@ -7,38 +7,65 @@ title:

## zh-CN

带有搜索按钮的输入框,`2.5.0` 时新增。
带有搜索按钮的输入框,`2.5.0` 时新增,3.14.0 后支持 `loading`

## en-US

Example of creating a search box by grouping a standard input with a search button, added in `2.5.0`.
Example of creating a search box by grouping a standard input with a search button, added in `2.5.0` and `loading` property is supported in `3.14.0`.

````jsx
import { Input } from 'antd';

const Search = Input.Search;

ReactDOM.render(
<div>
<Search
placeholder="input search text"
onSearch={value => console.log(value)}
style={{ width: 200 }}
/>
<br /><br />
<Search
placeholder="input search text"
onSearch={value => console.log(value)}
enterButton
/>
<br /><br />
<Search
placeholder="input search text"
enterButton="Search"
size="large"
onSearch={value => console.log(value)}
/>
</div>,
mountNode
);
class SearchDemo extends React.Component {
state = {
loading1: false,
loading2: false,
loading3: false,
};

handleSearch = (key, value) => {
console.log(value);
this.setState({
[key]: true,
});
setTimeout(() => {
this.setState({
[key]: false,
});
}, 3000);
}

render () {
const { loading1, loading2, loading3 } = this.state;
return (
<div>
<Search
placeholder="input search text"
onSearch={value => this.handleSearch('loading1', value)}
style={{ width: 200 }}
loading={loading1}
/>
<br /><br />
<Search
placeholder="input search text"
onSearch={value => this.handleSearch('loading2', value)}
enterButton
loading={loading2}
/>
<br /><br />
<Search
placeholder="input search text"
enterButton="Search"
size="large"
onSearch={value => this.handleSearch('loading3', value)}
loading={loading3}
/>
</div>
);
}
}

ReactDOM.render( <SearchDemo />, mountNode);
````
3 changes: 2 additions & 1 deletion components/input/index.en-US.md
Expand Up @@ -57,7 +57,8 @@ The rest of the props of `Input.TextArea` are the same as the original [textarea
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| enterButton | to show an enter button after input | boolean\|ReactNode | false |
| onSearch | The callback function that is triggered when you click on the search-icon or press Enter key. | function(value, event) | |
| onSearch | The callback function that is triggered when you click on the search-icon or press Enter key. It works when `loading` is false | function(value, event) | |
| loading | Searching status added in 3.15.0 | boolean | false |

Supports all props of `Input`.

Expand Down
3 changes: 2 additions & 1 deletion components/input/index.zh-CN.md
Expand Up @@ -54,7 +54,8 @@ Input 的其他属性和 React 自带的 [input](https://facebook.github.io/reac
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| enterButton | 是否有确认按钮,可设为按钮文字 | boolean\|ReactNode | false |
| onSearch | 点击搜索或按下回车键时的回调 | function(value, event) | |
| onSearch | 点击搜索或按下回车键时的回调,loading 为 false 时生效 | function(value, event) | |
| loading | 是否搜索中,版本 3.15.0 后新增 | boolean | false |

其余属性和 Input 一致。

Expand Down
8 changes: 8 additions & 0 deletions components/input/style/search-input.less
Expand Up @@ -15,6 +15,10 @@
}
}

&-loading {
cursor: default !important;
}

&:not(&-small) > .@{ant-prefix}-input-suffix {
right: @control-padding-horizontal;
}
Expand All @@ -27,6 +31,10 @@
}
}

&-button-text-loading {
margin-right: 12px;
}

&.@{search-prefix}-enter-button {
display: table;

Expand Down

0 comments on commit de250cd

Please sign in to comment.