【问题标题】:Updating angular reactive form model with values from outside使用外部值更新角反应形式模型
【发布时间】:2019-05-05 03:58:22
【问题描述】:

我想我有一个关于 Angular 表单处理的非常常见的问题,但是在搜索和阅读了几个小时后,我的问题没有找到任何答案。

问题:
我构建了一个响应式表单,如果用户处于角度上下文中(键入值等),一切都很好。但是当我使用像 Web Developer Form Filler 这样的 chrome 插件并用它填写表单时,模型不会更新。

为了重现这个问题,我在这里创建了一个小应用程序:https://stackblitz.com/edit/angular-ltrmpd

表单控制器:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  form = new FormGroup({
    name: new FormControl('Valid name', [
      Validators.required,
      Validators.minLength(5)
    ])
  });

  get name() { return this.form.get('name'); }

  onSubmit() {
    // reload all form data and revalidate, but how?

    if (this.form.valid) {
      alert('VALID');
    }
  }
}

表单视图:

<form [formGroup]="form" (ngSubmit)="onSubmit()">

  <div class="form-group row">
    <label for="name" class="col-sm-2 col-form-label">Name</label>
    <div class="col-sm-10">
      <input formControlName="name" type="text"class="form-control" id="name" [class.is-invalid]="name.invalid && name.touched" />
      <pre class="invalid-feedback">{{ name.errors | json }}</pre>
    </div>
  </div>

  <pre>{{ form.value | json }}</pre>
  <pre>form.valid: {{ form.valid }}</pre>

  <button type="button" class="btn btn-danger" onclick="document.getElementById('name').value = 'X'">SET VALUE FROM OUTSIDE</button> model doesn't update <br /><br />

  <button type="button" class="btn btn-success" (click)="name.patchValue('YYY')">SET VALUE ANGULAR WAY</button> updates the model right <br /><br />

  <button type="submit" class="btn btn-primary" [disabled]="!form.valid">Submit</button>
</form>
  • 默认表单值有效
  • 单击“从外部设置值”按钮 -> 模型不更新
  • 点击“提交” -> 您应该无法点击按钮,或者我们在点击按钮后手动更新模型和验证状态

我尝试过的最简单的解决方案是在用户提交表单后更新模型并重新验证。但是如何使用当前表单值更新模型?

我只发现了这个问题:How to update Angular 2 Reactive form field when changes occurred outside of Angular world。但我认为这不是同一个问题,因为我无法控制这个表单填充工具。

【问题讨论】:

  • 之后触发input事件怎么样?它解决了你的问题吗?无论如何,如果从外部世界更改了值,则必须通知 Angular 值已更改。 stackblitz.com/edit/angular-jybsvy?file=src/app/…
  • 如果我可以使用这个工具的功能,它会解决这个问题。用户使用 chrome 插件触发“填写表单”操作,并根据我发布的示例设置表单值。如果我可以说“从表单重新加载数据并将其写入模型”,那将是安全的,就像我上面提到的那样。

标签: javascript angular


【解决方案1】:

我一直在寻找相同的事件,最后查看了 @angular/core 包下的反应式表单实现,然后有一个 input 事件绑定到表单元素,它负责运行附加到该表单元素的验证器并更新 @ 987654325@.

所以要解决您的问题,您可以在同一个表单控件上调度输入事件。

示例 -

var event = new Event("input");
element.dispatchEvent(event);

如果您需要更深入地了解反应式表单的实现,那么您可以在下面查找。

注意-下面引用default_value_accessor.ts文件的行号。

在第 68 行 - 我们将输入事件绑定到最终调用 _handleInput 的宿主元素

host:      {
'(input)': '$any(this)._handleInput($event.target.value)',
'(blur)': 'onTouched()',
'(compositionstart)': '$any(this)._compositionStart()',
'(compositionend)': '$any(this)._compositionEnd($event.target.value)'
},

第 134 行 - 我们有 _handleInput 定义,它正在运行 onChange 回调,它负责从 validator.ts 运行 _executeValidators 函数。

/**@internal*/
_handleInput(value: any): void {
   if (!this._compositionMode || (this._compositionMode && !this._composing)) {
      this.onChange(value);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-30
    • 2020-04-03
    • 2013-07-28
    • 1970-01-01
    • 2021-11-25
    • 2020-11-07
    • 1970-01-01
    相关资源
    最近更新 更多