【问题标题】:Angular 2 TD form cannot setValue or patchValue to span tag, buttonAngular 2 TD 表单无法将值或补丁值设置为跨标签、按钮
【发布时间】:2019-01-08 10:27:48
【问题描述】:

我有一个简单的角度模板驱动表单,其中包含很少的输入、跨度标签和按钮。我需要 setValue 以从我的组件中的对象形成。

我无法将值设置为 span 和 button 标签,并且出现以下错误。

core.js:1365 ERROR Error: Uncaught (in promise): Error: No value accessor for form control with path: 'userSettings -> id'
Error: No value accessor for form control with path: 'userSettings -> id'
  at _throwError (forms.js:1901)
  at setUpControl (forms.js:1771)
  at resolvedPromise.then (forms.js:3851)
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
  at Object.onInvoke (core.js:3988)
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387)
  at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)
  at zone.js:870
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
  at Object.onInvokeTask (core.js:3979)
  at _throwError (forms.js:1901)
  at setUpControl (forms.js:1771)
  at resolvedPromise.then (forms.js:3851)
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
  at Object.onInvoke (core.js:3988)
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387)
  at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)
  at zone.js:870
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
  at Object.onInvokeTask (core.js:3979)
  at resolvePromise (zone.js:821)
  at zone.js:873
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
  at Object.onInvokeTask (core.js:3979)
  at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
  at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
  at drainMicroTaskQueue (zone.js:594)
  at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:499)
  at invokeTask (zone.js:1536)
  at HTMLAnchorElement.globalZoneAwareCallback (zone.js:1562)

我的表单html代码

<form class="form-horizontal" role="form" (ngSubmit)="onSettingUpdateSubmit()" #settingsForm="ngForm" >
<fieldset ngModelGroup="userSettings">
  <legend><strong>Account Settings</strong></legend>
  <br>

  <div class="form-group row">
    <label class="col-md-3  col-form-label text-md-right">Id</label>
    <div class="col-md-4">
      <span class="fw-semi-bold" [ngModel]="id" id="id" name="id">{{ id }}</span>
    </div>
  </div>

  <div class="form-group row">
    <label for="firstName" class="col-md-3  col-form-label text-md-right">First Name</label>
    <div class="col-md-4">
      <input type="text"
             id="firstName"
             required
             [ngModel]="firstName"
             name="firstName"
             class="form-control"
             placeholder="Your first name">
    </div>
  </div>

  <div class="form-group row">
    <label class="col-md-3  col-form-label text-md-right">Active</label>
    <div class="col-md-4">
      <button type="button"
              id="active"
              [value]="active"
              [ngModel]="active"
              name="active"
              [ngClass]="active ? 'btn btn-success' : 'btn btn-danger'"
              (click)="onActiveMode()">{{ active ? 'Yes' : 'No'}}</button>
    </div>
  </div>
</fieldset>

<div class="form-actions">
  <div class="btn-block text-center">
    <button type="submit"
            class="btn btn-primary"

            [disabled]=!settingsForm.valid>Update</button>
  </div>
</div>

我的组件中的 settingsService 将从我的 API 中返回一个对象,如下所示。

{
    "id":"12345",
    "firstName":"Victor",
    "active":true
}

我的 settings.compontent.ts

export class SettingsComponent implements OnInit {

 ngOnInit() {
      this.settingsService.getUserSettings('12345')
         .subscribe(
               (response: UserSettings) => {

                    console.log(response);

                    // this.settingForm.setValue({
                    //   userSettings: response
                    // });

                    this.settingForm.form.patchValue({
                       userSettings: response
                    });
                },
                (error) => console.log(error)
             );
           }

 onSettingUpdateSubmit() {
     console.log(this.settingForm.value.userSettings);
 }
}

当我单击表单中的更新按钮时,它会返回所有带有值的完整对象(在我的组件中预设用于测试目的)。

【问题讨论】:

  • setValuepatchValue 用于反应形式。您正在使用模板驱动的表单。对于模板驱动的表单,值通过双向绑定设置到控件中。
  • 我可以通过为 span 标签添加 ngDefaultControl="id" 来解决该错误。我正在使用 @ViewChild 访问我的完整表单,使用 ngModelGroup='userSettings' 所以,我使用 setValue 或 patchValue 进行整体设置。
  • 好的。但仅供参考……Angular 团队强烈建议不要混合使用模板驱动的表单语法和反应式表单语法。

标签: angular typescript angular2-forms


【解决方案1】:

您似乎将一些模板驱动的表单语法与反应式表单语法混合在一起,但它不起作用。

这是我的模板驱动表单控件之一的示例:

  <div class="form-group row">
    <label class="col-md-2 col-form-label"
           for="firstNameId">First Name</label>
    <div class="col-md-8">
      <input class="form-control"
             id="firstNameId"
             type="text"
             placeholder="First Name (required)"
             required
             minlength="3"
             [(ngModel)]=customer.firstName
             name="firstName"
             #firstNameVar="ngModel"
             [ngClass]="{'is-invalid': (firstNameVar.touched || firstNameVar.dirty) && !firstNameVar.valid }" />
      <span class="invalid-feedback">
        <span *ngIf="firstNameVar.errors?.required">
          Please enter your first name.
        </span>
        <span *ngIf="firstNameVar.errors?.minlength">
          The first name must be longer than 3 characters.
        </span>
      </span>
    </div>
  </div>

注意它使用双向绑定:[(ngModel)]=customer.firstName

它绑定到客户对象的 firstName 属性。在您的情况下,您需要定义一个 user 对象。像这样的:

export class SettingsComponent implements OnInit {
     user: UserSettings;

     ngOnInit() {
          this.settingsService.getUserSettings('12345')
             .subscribe(
                   (response: UserSettings) => {
                        console.log(response);
                        this.user = response;
                    },
                    (error) => console.log(error)
                 );
               }

     onSettingUpdateSubmit() {
         console.log(this.settingForm.value.userSettings);
     }
    }

还有你的 HTML:

[(ngModel)]="user.firstName"

这将使用从您的设置服务检索到的值自动填充您的表单。

我这里有一个完整的例子:https://github.com/DeborahK/Angular2-ReactiveForms/tree/master/Demo-Start-Updated

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 2021-06-16
    • 2015-06-16
    • 1970-01-01
    • 2016-09-13
    • 2022-11-24
    • 2020-01-11
    相关资源
    最近更新 更多