Angular 6中autocomplete设为email却自动变为off的问题
这个问题我在Angular 6项目里碰到过好几次,属实是框架默认行为挖的小坑,咱们来好好拆解下原因和解决办法:
Angular的响应式表单控件(FormControl)在初始化过程中,会自动给关联的input元素设置autocomplete="off"。这是框架的默认设计,目的是避免浏览器自动填充功能干扰表单的状态检测(比如脏值、触摸状态的判断)。哪怕你在模板里手动写了autocomplete="email",Angular也会在控件初始化完成后把这个属性覆盖成off,这就是你看到浏览器提示和最终HTML里值变成off的原因。
针对Angular 6,这里有几个经过验证的靠谱方案:
方案一:组件类中手动设置属性
通过ViewChild获取到input元素,在ngAfterViewInit生命周期钩子中手动设置autocomplete属性,这样能确保覆盖Angular的默认设置:import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; @Component({ selector: 'app-login-form', templateUrl: './login-form.component.html' }) export class LoginFormComponent implements AfterViewInit { loginForm = new FormGroup({ login: new FormControl('', [Validators.required, Validators.email]) }); @ViewChild('loginInput') loginInput: ElementRef; ngAfterViewInit() { this.loginInput.nativeElement.setAttribute('autocomplete', 'email'); } }对应的模板里需要给input加个模板引用变量:
<div class="form-group"> <label for="login">E-mail cim</label> <input #loginInput autocomplete='email' formControlName="login" type="email" id="login" class="form-control" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" name="login"> </div>小提示:这里把input的
type从login改成了标准的email,更符合HTML语义规范哦。方案二:自定义指令统一处理
如果你的项目里多个表单都有这个需求,可以写一个简单的指令来批量解决,避免重复代码:import { Directive, ElementRef, OnInit } from '@angular/core'; @Directive({ selector: '[appAutocompleteFix]' }) export class AutocompleteFixDirective implements OnInit { constructor(private el: ElementRef) {} ngOnInit() { const targetValue = this.el.nativeElement.getAttribute('autocomplete'); if (targetValue) { // 用setTimeout确保在Angular初始化完成后再修改 setTimeout(() => { this.el.nativeElement.setAttribute('autocomplete', targetValue); }, 0); } } }然后在模板里给需要的input加上这个指令就行:
<input appAutocompleteFix autocomplete='email' formControlName="login" type="email" id="login" class="form-control" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" name="login">方案三:尝试添加
ngDefaultControl
给input加上ngDefaultControl属性,有时候能让Angular跳过自动设置autocomplete="off"的逻辑,不过这个方法在部分场景下稳定性稍差,可以先试试:<input autocomplete='email' formControlName="login" type="email" id="login" class="form-control" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" name="login" ngDefaultControl>
内容的提问来源于stack exchange,提问作者user8778731

