繁体   English   中英

有没有办法为 angular 反应形式启用自动完成功能?

[英]Is there a way to enable the autocomplete for angular reactive form?

我想为 angular 表单设置autocomplete属性,但它没有按预期工作。 它只记住我第一次提交的值,无论我点击多少次提交按钮,我都想记住并建议所有值。

是我尝试过的代码的堆栈闪电战。

<form
  autocomplete="on"
  (ngSubmit)="onSubmit()"
  name="filtersForm"
  [formGroup]="formGroup1"
>
  <div>
    <label>First Name</label>
    <input
      id="firstName"
      name="firstName"
      autocomplete="on"
      formControlName="firstName"
    />
  </div>
  <div>
    <label>Last Name</label>
    <input
      id="firstName"
      name="lastName"
      autocomplete="on"
      formControlName="lastName"
    />
  </div>
  <button type="submit">Submit</button>
</form>

以下是我使用的autocomplete属性的详细信息。

在 Firefox 中,多次单击提交按钮后,自动完成工作正常,问题出在 Chrome 和 Edge 中。

有没有办法让自动完成功能适用于 angular 表单中的输入?

autocomplete属性仅适用于提交的值。 它与 Angular 无关。

https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete

如果您需要一些自定义行为,那么您最好创建自己的组件来自动完成用户的输入,这样您就可以使用一些默认值,在模糊中添加更多的值等。

您只需要删除输入标签中的autocomplete="on"即可。 使用 chrome,我们只在表单元素中添加属性autocomplete="on" ,它将缓存用户输入到输入文本中的所有值。 结果将是这样的: 在此处输入图像描述

<form
  autocomplete="on"
  (ngSubmit)="onSubmit()"
  name="filtersForm"
  [formGroup]="formGroup1"
>
  <div>
    <label>First Name</label>
    <input
      id="firstName"
      name="firstName"
      formControlName="firstName"
    />
  </div>
  <div>
    <label>Last Name</label>
    <input
      id="firstName"
      name="lastName"
      formControlName="lastName"
    />
  </div>
  <button type="submit">Submit</button>
</form>

您必须使用所需选项创建一个数组,该数组应显示为自动完成。 您可以在这里查看https://material.angular.io/components/autocomplete/examples ,有多个示例可以帮助您。 即使你没有使用 Angular 材料,逻辑也是一样的

我想,我找到了一种解决方法,它只适用于模板驱动表单。


TLDR;

我在处理这个问题时发现了什么。

  • 在第一个form提交时, autofill只记住第一次提交的值
  • form提交POST方法可以记住所有值。

是的,从上面看,显然第二种方式适合我们。 但是为什么有人会做表单POST来向 BE 提交表单。 应该有更好的方法来解决这个问题。 否则我们将不得不考虑处理 PostBack 😃😃(FW like.Net 通过保留隐藏的input来做到这一点)。

别担心,我们可以在这里做一些解决方法来避免表单POST 我找到了在不刷新页面的情况下处理 POST 调用的答案

使用普通的 HTML 和 JS工作 JSBin

AutoCompleteSaveForm = function(form){
    var iframe = document.createElement('iframe');
    iframe.name = 'uniqu_asdfaf';
    iframe.style.cssText = 'position:absolute; height:1px; top:-100px; left:-100px';
    document.body.appendChild(iframe);
    var oldTarget = form.target;
    var oldAction = form.action;
    form.target = 'uniqu_asdfaf';
    form.action = '/favicon.ico';
    form.submit();
    setTimeout(function(){
        form.target = oldTarget;
        form.action = oldAction;
        document.body.removeChild(iframe);
    });
}

基本上我们在表单属性上改变了一些东西。

  1. target="iframe_name" - 连接到 iFrame 以避免页面刷新。
  2. method="POST" - POST 调用
  3. url="/favicon" - API url 到 favicon(轻量级调用)

在 angular 中,您可以为其创建一个指令。

import { 
  Directive, ElementRef, EventEmitter,
  HostBinding, HostListener, Input, Output,
} from '@angular/core';

@Directive({
  selector: '[postForm]',
})
export class PostFormDirective {
  @HostBinding('method') method = 'POST';

  @HostListener('submit', ['$event'])
  submit($event) {
    $event.preventDefault();
    this.autoCompleteSaveForm(this.el.nativeElement);
  }

  constructor(private el: ElementRef) {}

  autoCompleteSaveForm(form) {
    let iframe = document.querySelector('iframe');
    if (!iframe) {
      iframe = document.createElement('iframe');
      iframe.style.display = 'none';
    }
    iframe.name = 'uniqu_asdfaf';

    document.body.appendChild(iframe);
    var oldTarget = form.target;
    var oldAction = form.action;
    form.target = 'uniqu_asdfaf';
    form.action = '/favicon.ico'; // dummy action
    form.submit();
    setTimeout(() => {
      // set back the oldTarget and oldAction
      form.target = oldTarget;
      form.action = oldAction;
      // after form submit 
      this.onSubmit.emit();
    });
  }

  @Output() onSubmit = new EventEmitter();

  ngOnDestroy() {
    let iframe = document.querySelector('iframe');
    if (iframe) {
      document.body.removeChild(iframe);
    }
  }
}

好的,到目前为止一切顺利。 然后我开始将它集成到formGroup (模型驱动表单)中,不知何故它不起作用。 下次这些字段时它不会存储值。

<form (ngSubmit)="onSubmit()" [formGroup]="formGroup1" autocomplete="on">
  <div>
    <label>First Name</label>
    <input id="firstName" name="firstName" formControlName="firstName" />
  </div>
  <div>
    <label>Last Name</label>
    <input id="lastName" name="lastName" formControlName="lastName" />
  </div>
  <button>Submit</button>
</form>

后来我用模板驱动表单尝试了同样的方法。 它就像一个魅力。 我没有深入探讨为什么它不适用于 Model 驱动形式(也许调查可能会占用更多时间)

<form #form1="ngForm" ngForm postForm (onSubmit)="onSubmit(form1)">
  <ng-container [ngModelGroup]="userForm">
    <div>
      <label>First Name</label>
      <input name="firstName" [(ngModel)]="userForm.firstName" />
    </div>
    <div>
      <label>Last Name</label>
      <input name="lastName" [(ngModel)]="userForm.lastName" />
    </div>
  </ng-container>

  <button>Submit</button>
</form>

是的,我刚一开始就说过它只适用于模板驱动表单。 所以你必须切换到模板。 还有一件更重要的事情要注意,您可能会想到创建虚拟 POST api 调用,它可以是轻量级的,而不是点击图标。

堆栈闪电战

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM