diff --git a/components/input/Password.tsx b/components/input/Password.tsx
index 9556f1c8e7..d1a428a6b8 100644
--- a/components/input/Password.tsx
+++ b/components/input/Password.tsx
@@ -1,5 +1,6 @@
import classNames from '../_util/classNames';
import { getComponent, getOptionProps } from '../_util/props-util';
+import { cloneElement } from '../_util/vnode';
import Input from './Input';
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
import EyeInvisibleOutlined from '@ant-design/icons-vue/EyeInvisibleOutlined';
@@ -23,6 +24,9 @@ export default defineComponent({
inputPrefixCls: PropTypes.string.def('ant-input'),
action: PropTypes.string.def('click'),
visibilityToggle: PropTypes.looseBool.def(true),
+ iconRender: PropTypes.func.def((visible: boolean) =>
+ visible ? : ,
+ ),
},
setup() {
return {
@@ -55,6 +59,8 @@ export default defineComponent({
getIcon() {
const { prefixCls, action } = this.$props;
const iconTrigger = ActionMap[action] || '';
+ const iconRender = this.$slots.iconRender || this.$props.iconRender;
+ const icon = iconRender(this.visible);
const iconProps = {
[iconTrigger]: this.onVisibleChange,
onMousedown: (e: Event) => {
@@ -70,11 +76,7 @@ export default defineComponent({
class: `${prefixCls}-icon`,
key: 'passwordIcon',
};
- return this.visible ? (
-
- ) : (
-
- );
+ return cloneElement(icon, iconProps);
},
},
render() {
diff --git a/components/input/__tests__/index.test.js b/components/input/__tests__/index.test.js
index 684411905c..944e86d748 100644
--- a/components/input/__tests__/index.test.js
+++ b/components/input/__tests__/index.test.js
@@ -3,6 +3,7 @@ import { asyncExpect } from '@/tests/utils';
import Input from '..';
// import Form from '../../form';
import focusTest from '../../../tests/shared/focusTest';
+import { WifiOutlined, SyncOutlined } from '@ant-design/icons-vue';
const { TextArea, Password } = Input;
@@ -131,3 +132,35 @@ describe('Input.Search', () => {
}, 100);
});
});
+
+describe('Input.Password', () => {
+ it('should support iconRender', async () => {
+ const wrapper = mount(Input.Password, {
+ props: { iconRender: visible => (visible ? : ) },
+ sync: false,
+ });
+ await asyncExpect(() => {
+ expect(wrapper.findAll('.anticon-wifi').length).toBe(1);
+ wrapper.find('.anticon-wifi').trigger('click');
+ }, 100);
+ await asyncExpect(() => {
+ expect(wrapper.findAll('.anticon-sync').length).toBe(1);
+ }, 100);
+ });
+
+ it('should support slot iconRender', async () => {
+ const wrapper = mount(Input.Password, {
+ slots: {
+ iconRender: visible => (visible ? : ),
+ },
+ sync: false,
+ });
+ await asyncExpect(() => {
+ expect(wrapper.findAll('.anticon-wifi').length).toBe(1);
+ wrapper.find('.anticon-wifi').trigger('click');
+ }, 100);
+ await asyncExpect(() => {
+ expect(wrapper.findAll('.anticon-sync').length).toBe(1);
+ }, 100);
+ });
+});