当chrome在初始页面加载时预填充文本框时,TextField概述的变体中存在显示问题。 自动填充的文本将覆盖标签。 请参见下面的屏幕截图。
还要注意自动填充文本的黄色背景,可以覆盖它吗?
MUI版本3.9.2
这需要解决这个问题! #14453可能提供一些解决问题的方法。
@garygrubb我想知道,您能否创建一个复制示例,以供我们一贯用来解决问题? 谢谢! 这看起来非常接近Google主登录表单:
回复较晚,抱歉。 如果时间允许,我将在本周晚些时候尝试制作一个小型复制品。 同时,我有一个临时修复程序-在任何一个文本字段上设置autoFocus即可解决此问题。
` <TextField
required
**autoFocus**
variant="outlined"
id="username"
label="mobile number"
defaultValue=""
margin="normal"
name="username"
type="tel"
onChange={this.handleChange}
error={!this.state.validMobile}
autoComplete="tel-national username"
/>
在任一文本字段上设置autoFocus即可解决此问题。
似乎不适合我。
还要注意自动填充文本的黄色背景,可以覆盖它吗?
@garygrubb我是通过主题覆盖实现的:
const theme = createMuiTheme({
overrides: {
MuiInputBase: {
input: {
'&:-webkit-autofill': {
transitionDelay: '9999s',
transitionProperty: 'background-color, color',
},
},
},
},
});
不理想,但这是事实。
另一种方法是使用阴影框填充输入: https :
@oliviertassinari这可能会解决问题: https : //stackoverflow.com/a/41530164/396889
此外,仅供参考: https :
@MarkMurphy知道我该如何重现该问题吗?
@MarkMurphy知道我该如何重现该问题吗?
对我来说,我创建了一个简单的用户名和密码表单,并允许Chrome记住我的凭据。
在MacOS High Sierra 10.13.6上使用Chrome 72.0.3626.119
@ material-ui /核心版本“ 3.8.1”
@ material-ui / styles版本“ 3.0.0-alpha.6”
@MarkMurphy我可以使用https://material-ui.com/getting-started/page-layout-examples/sign-in/复制它:
这是文本字段标准变体。 因此,我们可以注意到两个问题:
让我们现在尝试概述的变体。 我们可以使用此页面: https :
好像是铬自动填充问题。 如果我们提供了检测chrome自动填充的方法,那将是一个简单的解决方案...但是我不知道有任何解决方案。 唯一的解决方案是关闭所有文本字段的自动填充/自动填充。
@ ymoon715至少还有一个可行的解决方案,我在上面发布了一个链接。
感谢@cezarderevlean ,我摆脱了黄色背景,现在只需要弄清楚如何删除灰色的帮助程序文本即可。
如果您不想按照我上面第一个链接中的说明“禁用”自动填充,请记住,自动填充后,仅当通过更改代码刷新页面刷新时,它才会在屏幕快照中显示
开发(据我测试)。 正常的浏览器加载/刷新会很好,它将使占位符缩小。
另外,如果我上面所说的话是不正确的,那么您可以实现的一种解决方法是,始终在TextField
上放置占位符,以缩小占位符:
InputLabelProps={{
shrink: true,
}}
@cezarderevlean谢谢。 你是对的。 正常的浏览器刷新效果很好。
我不知道我怎么想念它,但是@MarkMurphy也有类似的解决方法,它使用了材质主题覆盖,这对于用例来说有点干净。 谢谢马克。
如果您不想按照我上面第一个链接中的说明“禁用”自动填充,请记住,自动填充后,仅当通过更改代码刷新页面刷新时,它才会在屏幕快照中显示
开发(据我测试)。 正常的浏览器加载/刷新会很好,它将使占位符缩小。另外,如果我上面所说的话是不正确的,那么您可以实现的一种解决方法是,始终在
TextField
上放置占位符,以缩小占位符:InputLabelProps={{ shrink: true, }}
谢谢,这对我有用。
在用户名字段上设置autoFocus
在密码字段上设置autoComplete='new-password'
对我也有用。
更新:我想我在这里跳了枪。 有什么想法吗?
对于想要获取输入的实际值而不只是检测值的存在的人们(请参阅https://github.com/mui-org/material-ui/issues/14427#issuecomment-466054906),我将我们提出了本文中详述的解决方案: https :
componentDidMount() {
var evt = new MouseEvent("click", {
view: window,
clientX: 0
});
window.dispatchEvent(evt);
let iterations = 0;
const interval = setInterval(() => {
const value = this.inputs.email.value;
// plain js alternative:
// const value = document.getElementById("email").value;
if (!!value || iterations > 20) {
console.log(value);
return clearInterval(interval);
}
iterations++;
console.log("not found -> repeat");
}, 100);
}
基本上,我强迫鼠标单击输入,以便Chrome在输入上设置值。 然后在稍后的值准备就绪时,我获取了该值。 它绝对是hacky,但是Chrome让我们别无选择...(在SO文章中查看Chrome立场的详细信息)。
TL; DR:这是浏览器问题。 自动填充表单时,它们不会始终触发输入事件。
这是浏览器级别的问题。 如果我在页面内单击,然后正确地重新加载,则会调度输入事件。 如果我单击该页面,请在导航栏中单击,它将仅在第二个Enter上停止工作。 如果我通过将链接复制到页面并在导航栏中输入它来进入页面,那么它也可以使用。
我什至不确定我们是否可以为所有浏览器修复此问题,因为在轮询时,即使自动填充,输入值仍为空。 仅适用于Chrome浏览器有一个巧妙的窍门。 如果只有铬有这些问题,将进行调查。
@ eps1lon如果与Chromium相关,您是否在Chromium中打开了一个错误?
这对我不起作用: https :
确实可行:InputLabelProps = {{收缩:true}},尽管它始终保持收缩
以下差异似乎可以解决该问题:
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
index d258e5b71d..a7aebb1288 100644
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -311,6 +311,10 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
}
};
+ // Check the input state on mount, in case it was filled by the user
+ // or auto filled by the browser before the hydration (for ssr).
+ React.useEffect(() => {
+ checkDirty(inputRef.current);
+ }, []);
+
const handleClick = event => {
if (inputRef.current && event.currentTarget === event.target) {
inputRef.current.focus();
谁能确认修复程序的质量?
@oliviertassinari需要在材料ui中具有工作组件,但是,如果这是上述@ eps1lon的Chromium错误,则此解决方法应仅是暂时的,并且应在Chromium中解决。 您可以确认这是Chromium中的错误还是仅仅是MUI错误?
如果是Chromium错误,我们应该检查是否为此打开了一个铬错误,如果没有打开,请问如何解决? 类似于:铬的搜索结果
(https://github.com/mui-org/material-ui/issues/14427#issuecomment-524535710)
目前,我认为这与Chrome无关。 我认为这是React和服务器端渲染的问题。 如果用户将内容写在输入中,那么在React水合物出现之前,我们永远不会收到通知: https :
@oliviertassinari但是在create-react-app开发服务器中没有发生服务器端渲染?
问题很可能是需要通过javascript设置任何onInput或onChange处理程序。 如果在chrome自动填充后发生这种情况,这些事件将丢失。 JavaScript越多,您越有可能松开事件。 React开始努力减少事件触发的时间,而React没有捕获到这些事件。 这将有助于水合的用户界面。
另一个问题是,尽管该值是自动填充的,但有时未设置input.value
。 仅在聚焦/模糊可能具有意外副作用的输入(例如,表单验证)之后。
由于几乎没有报告具有可复制的示例,因此很难对此问题进行适当的研究。 尽管从理论上来说, @ oliviertassinari的修复程序https://github.com/mui-org/material-ui/issues/14427#issuecomment -530145849看起来应该至少涵盖了问题,但在正确识别问题之前,我们不应该应用任何修复程序掉落的事件。
@ eps1lon有趣。 我建议的差异关注于我可以在https://material-ui.com/getting-started/page-layout-examples/sign-in/ (在开发模式下,在我的本地环境中)上可以重现的唯一问题。 我需要运行最后一个测试(同步侦听change事件),以确认“水合之前触发的事件”是问题的根源。 我认为这是值得处理的,至少在React对https://github.com/facebook/react/issues/12955表现出兴趣之前
@croraf您如何用CRA重现该问题?
我相信“水合作用之前触发的事件”问题也会在https://github.com/mui-org/material-ui/issues/14132#issuecomment -453657016中影响我们。
@oliviertassinari CRA在这里无关紧要,但是以下代码可以与CRA一起使用(也许此codeandbox甚至在内部使用CRA): https ://codesandbox.io/s/textinput-bug-hsv9m
A)要在此代码和框中重现它:
1)在新窗口中打开此沙盒的应用预览。
2)输入并保存凭据(Chrome对话框要求保存凭据后)
3)刷新窗口以查看问题(因为Chrome将应用自动填充功能)。 刷新时并不会始终出现此问题,但是双击F5(快速两次刷新)几乎可以始终如一地再现该问题。
B)我也发现了类似的东西
1)在codesandbox应用程序预览中(不在单独的应用程序窗口中)。
2)填写并提交表格(以便Chrome存储用户名/密码组合)
3)仅重新加载应用程序预览。 表格不会立即自动填写。 (在material-ui沙箱中,您只能删除字段的自动填充内容)
4)单击用户名文本字段。 Chrome会为您选择用户。
5)将鼠标悬停在密码字段上,然后查看发生的问题。
@ eps1lon说问题可能是Chrome在设置处理程序之前触发了与自动填充相关的事件。
但是Chrome如何在React在DOM中创建输入文件之前自动填充,以及React如何在javascript运行足以设置事件处理程序之前在DOM中创建输入文件?
对我来说,这似乎有些可疑,并且可能与SSR一起发生(尽管我不知道它是如何工作的)。 但是CRA开发服务器不使用SSR。
@ eps1lon说问题可能是Chrome在设置处理程序之前触发了与自动填充相关的事件。
这仅适用于通过反应而水合的静态html,并且仅在理论上进行了构造,因为我们目前尚无复制品。 现在,我们可以调查实际问题了。
我无法在Chrome v76.0.3809.132,macOS v10.14.6上重现该问题。
我可以在Windows 10的Chrome v76.0.3809.87上重现部分问题。
我可以在相同的设置(Chrome v76.0.3809.132,macOS v10.14.6)上重现该问题。
我的解决方案:
import { isChrome, osName} from "react-device-detect";
.....
.....
const isChromeOSX = osName === 'Mac OS' && isChrome
const [shrink, setShrink] = useState(isChromeOSX ? true : undefined)
useEffect(() => {
if(isChromeOSX) {
const listen = () => {
setShrink(undefined)
window.removeEventListener('click',listen)
}
window.addEventListener('click', listen);
return () => {
window.removeEventListener('click',listen)
};
}
}, [])
return <TextField
.....
variant="outlined"
InputLabelProps={{ shrink }}
/>
以下差异解决了我可以重现的问题,有人可以确认吗?
diff --git a/packages/material-ui/src/FormControl/FormControl.js b/packages/material-ui/src/FormControl/FormControl.js
index 0ede7ca404..c7cb22aeb9 100644
--- a/packages/material-ui/src/FormControl/FormControl.js
+++ b/packages/material-ui/src/FormControl/FormControl.js
@@ -145,6 +145,14 @@ const FormControl = React.forwardRef(function FormControl(props, ref) {
};
}
+ const onFilled = React.useCallback(() => {
+ setFilled(true);
+ }, []);
+
+ const onEmpty = React.useCallback(() => {
+ setFilled(false);
+ }, []);
+
const childContext = {
adornedStart,
disabled,
@@ -156,16 +164,8 @@ const FormControl = React.forwardRef(function FormControl(props, ref) {
onBlur: () => {
setFocused(false);
},
- onEmpty: () => {
- if (filled) {
- setFilled(false);
- }
- },
- onFilled: () => {
- if (!filled) {
- setFilled(true);
- }
- },
+ onEmpty,
+ onFilled,
onFocus: () => {
setFocused(true);
},
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
index d258e5b71d..9cb6c94f43 100644
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -116,6 +116,13 @@ export const styles = theme => {
'&$disabled': {
opacity: 1, // Reset iOS opacity
},
+ '&:-webkit-autofill': {
+ animationDuration: '5000s',
+ animationName: '$auto-fill',
+ },
+ },
+ '<strong i="6">@keyframes</strong> auto-fill': {
+ from: {},
},
/* Styles applied to the `input` element if `margin="dense"`. */
inputMarginDense: {
@@ -239,17 +246,20 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
}
}, [muiFormControl, disabled, focused, onBlur]);
+ const onFilled = muiFormControl && muiFormControl.onFilled;
+ const onEmpty = muiFormControl && muiFormControl.onEmpty;
+
const checkDirty = React.useCallback(
obj => {
if (isFilled(obj)) {
- if (muiFormControl && muiFormControl.onFilled) {
- muiFormControl.onFilled();
+ if (onFilled) {
+ onFilled();
}
- } else if (muiFormControl && muiFormControl.onEmpty) {
- muiFormControl.onEmpty();
+ } else if (onEmpty) {
+ onEmpty();
}
},
- [muiFormControl],
+ [onFilled, onEmpty],
);
useEnhancedEffect(() => {
@@ -311,6 +321,12 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
}
};
+ // Check the input state on mount, in case it was filled by the user
+ // or auto filled by the browser before the hydration (for SSR).
+ React.useEffect(() => {
+ checkDirty(inputRef.current);
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
+
const handleClick = event => {
if (inputRef.current && event.currentTarget === event.target) {
inputRef.current.focus();
@@ -354,6 +370,10 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
};
}
+ const handleAutoFill = () => {
+ // Provide a fake value as Chrome might not let you access it for security reasons.
+ checkDirty({ value: 'x' });
+ };
+
return (
<div
className={clsx(
@@ -399,6 +419,7 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
defaultValue={defaultValue}
disabled={fcs.disabled}
id={id}
+ onAnimationStart={handleAutoFill}
name={name}
onBlur={handleBlur}
onChange={handleChange}
一部分的灵感来自https://github.com/tocco/tocco-client/commit/cb3b9b59994380f17c6650ffe4b63f96948072b6。
我使用material-ui沙箱(“文档”页面)在本地测试了此修复程序,并且在应用此问题时无法重现该问题。
这是问题所在:
使用此修复程序,我无法重现https://github.com/mui-org/material-ui/issues/14427#issuecomment -530503051 B部分中提到的类似问题
在这里看到的一个:
@oliviertassinari @ eps1lon我在业务应用程序中测试了v4.4.3,但没有看到错误。 因此,似乎该补丁程序(尽管可能不是最优雅的)解决了该问题,并且我删除了该hack程序,以使其始终引发标签( InputLabelProps={{ shrink: true }}
并不是一个很好的hack程序,因为即使输入内容也被增加了,字段为空)。
@oliviertassinari @ eps1lon
不幸的是,我确实有一个新的小问题。 使用自动填充功能时。 选择用户,然后删除密码,然后尝试再次选择(或类似的选项),即使字段为空,标签也保持上升:/
->
铬:77
Ubuntu的:18.04
@oliviertassinari @ eps1lon @croraf我也在我的应用程序中对其进行了测试,该问题不再存在。 谢谢你的帮助。
@garygrubb尝试看看您是否注意到我在上面的帖子中提到的细微错误。
@coraf是的,我能够在台式机Chrome版本76.0.3809.132(正式版本)(64位)上重现同样的问题。 移动版本和Firefox似乎还可以。
如果您为此打开一个新期刊,请标记我,以便我继续。
以下帮助吗?
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
index 439e8afa7..f0ab8bb66 100644
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -373,6 +373,12 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
}
const handleAutoFill = () => {
+ // The change event is correcty triggered when the input is focused.
+ // There is no need to detect autofill.
+ if (fcs.focused) {
+ return;
+ }
+
// Provide a fake value as Chrome might not let you access it for security reasons.
checkDirty({ value: 'x' });
};
@oliviertassinari好,我在mui docs页面上找到了剩余问题的一致复制。
注意:与原始问题相比,剩下的问题实际上是一件小事,而且可能不是那么高。
刷新http:// localhost :3000 / components / text-fields#outlined
我得到类似的东西:
手动删除电子邮件字段,但密码仍自动填写
localhost:3000
)您将得到这种情况:
@oliviertassinari您的其他修补程序似乎可以解决我描述的其余问题。
但我发现了该问题的另一种味道:D
再现步骤与上述类似,但是在步骤3中,还手动清除了密码:
最后将给您以下结果问题
最后将给您以下结果问题
@croraf哦,天哪,我还没看到这个呢! 是的,这很有意义。
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
index 763ab105c..9dce66f9d 100644
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -86,6 +86,7 @@ export const styles = theme => {
// Make the flex item shrink with Firefox
minWidth: 0,
width: '100%', // Fix IE 11 width issue
+ animationName: '$auto-fill-cancel',
'&::-webkit-input-placeholder': placeholder,
'&::-moz-placeholder': placeholder, // Firefox 19+
'&:-ms-input-placeholder': placeholder, // IE 11
@@ -123,6 +124,9 @@ export const styles = theme => {
'<strong i="9">@keyframes</strong> auto-fill': {
from: {},
},
+ '<strong i="10">@keyframes</strong> auto-fill-cancel': {
+ from: {},
+ },
/* Styles applied to the `input` element if `margin="dense"`. */
inputMarginDense: {
paddingTop: 4 - 1,
@@ -380,9 +384,11 @@ const InputBase = React.forwardRef(function InputBase(props, ref) {
};
}
- const handleAutoFill = () => {
+ const handleAutoFill = event => {
// Provide a fake value as Chrome might not let you access it for security reasons.
- checkDirty({ value: 'x' });
+ checkDirty(
+ event.animationName.indexOf('auto-fill-cancel') !== -1 ? inputRef.current : { value: 'x' },
+ );
};
return (
从:
4.4.2
4.4.3
建议的补丁
@ oliviertassinari , @ croraf-在生产中
请在其他您希望我进行测试的错误修复中标记我。 我很乐意提供帮助。
很高兴听到它。
不支持深色主题?
@MAkerboom我们可以考虑将颜色更改为较深的蓝色。 您想尝试一下这种东西吗?
@oliviertassinari ,只要显示轮廓,并且仍然与文本有足够的对比度,对我来说就很好
@MAkerboom我能
diff --git a/packages/material-ui/src/FilledInput/FilledInput.js b/packages/material-ui/src/FilledInput/FilledInput.js
index 71d0bcc94..4b681cba1 100644
--- a/packages/material-ui/src/FilledInput/FilledInput.js
+++ b/packages/material-ui/src/FilledInput/FilledInput.js
@@ -106,6 +106,12 @@ export const styles = theme => {
/* Styles applied to the `input` element. */
input: {
padding: '27px 12px 10px',
+ '&:-webkit-autofill': {
+ WebkitBoxShadow: theme.palette.type === 'dark' ? '0 0 0 100px #266798 inset' : null,
+ WebkitTextFillColor: theme.palette.type === 'dark' ? '#fff' : null,
+ borderTopLeftRadius: 'inherit',
+ borderTopRightRadius: 'inherit',
+ },
},
/* Styles applied to the `input` element if `margin="dense"`. */
inputMarginDense: {
diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.js b/packages/material-ui/src/OutlinedInput/OutlinedInput.js
index f60c4e5d5..376e37ba8 100644
--- a/packages/material-ui/src/OutlinedInput/OutlinedInput.js
+++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.js
@@ -65,6 +65,11 @@ export const styles = theme => {
/* Styles applied to the `input` element. */
input: {
padding: '18.5px 14px',
+ '&:-webkit-autofill': {
+ WebkitBoxShadow: theme.palette.type === 'dark' ? '0 0 0 100px #266798 inset' : null,
+ WebkitTextFillColor: theme.palette.type === 'dark' ? '#fff' : null,
+ borderRadius: theme.shape.borderRadius,
+ },
},
/* Styles applied to the `input` element if `margin="dense"`. */
inputMarginDense: {
你可以吗? 您要提交拉取请求吗? :)
好多了! 谢谢。 将尝试进行公关
我在使用<AutoComplete/>
看到了此错误。 当重点关注文本字段时,该文本字段不会“缩小”其标签。 我在Firefox和Chrome中看到了这一点(未测试其他浏览器)。 从v4.5.0升级到v4.5.2修复了该问题。 我相信与此问题相关的PR负责任,所以谢谢!
FWIW这是一个主题替代,可以防止chrome在自动填充的输入上显示自定义颜色:
theme = {
overrides: {
MuiInputBase: {
root: {
fontFamily: '"Lato", serif',
"& input": {
"&:-webkit-autofill": {
transition:
"background-color 50000s ease-in-out 0s, color 50000s ease-in-out 0s",
},
"&:-webkit-autofill:focus": {
transition:
"background-color 50000s ease-in-out 0s, color 50000s ease-in-out 0s",
},
"&:-webkit-autofill:hover": {
transition:
"background-color 50000s ease-in-out 0s, color 50000s ease-in-out 0s",
},
},
},
},
}
}
@armellarcier感谢您的分享。 我会小心删除自定义颜色,我认为这是为了帮助用户。 从安全的角度来看,这也可能很有趣,以便更好地了解您使用的是正确的域名,而不是被钓鱼(否则自动填充无效)
最有用的评论
@garygrubb我是通过主题覆盖实现的:
不理想,但这是事实。
另一种方法是使用阴影框填充输入: https :