将 "provideForms()" 添加到我的 main.ts 后,模板驱动表单出现问题

Issue with template-driven forms after adding "provideForms()" to my main.ts

我最近开始迁移到模型驱动表单而不是模板驱动表单。

我不得不在我的 main.ts 中添加一个 provideForms(),

从那时起,我所有的模板驱动表单都会引发异常,例如:

Reference "#firstNameForm" is defined several times

完整消息如下:

browser_adapter.ts:82 EXCEPTION: Error: Uncaught (in promise): Template parse errors:
Reference "#firstNameForm" is defined several times ("<h4>{{'FIRST_NAME_FORM.TITLE' | translate}}</h4>
<form (ngSubmit)="updateFirstName(firstNameForm)" [ERROR ->]#firstNameForm="ngForm" novalidate>
    <div class="form-group" [ngClass]="getCssClasses(firstNameFor"): UserAccountFirstNameComponent@1:50BrowserDomAdapter.logError @ browser_adapter.ts:82BrowserDomAdapter.logGroup @ browser_adapter.ts:93ExceptionHandler.call @ exception_handler.ts:58(anonymous function) @ application_ref.ts:374schedulerFn @ async.ts:148SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ async.ts:133onError @ ng_zone.ts:142onHandleError @ ng_zone_impl.ts:95ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
browser_adapter.ts:82 STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:82ExceptionHandler.call @ exception_handler.ts:61(anonymous function) @ application_ref.ts:374schedulerFn @ async.ts:148SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ async.ts:133onError @ ng_zone.ts:142onHandleError @ ng_zone_impl.ts:95ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426

组件文件如下:

import {Component, OnInit} from "@angular/core";
import {ControlGroup, NgClass} from "@angular/common";
import {ROUTER_DIRECTIVES, Router} from "@angular/router";
import {TranslatePipe} from "ng2-translate/ng2-translate";
import {UserAccountService} from "../useraccount.service";
import {AppConstants} from "../../shared/app-constants";
import {StylingService} from "../../shared/services/styling.service";
import {UserAccount} from "../../shared/models/useraccount.model";


@Component({
  moduleId: module.id,
  templateUrl: 'useraccount-firstname.component.html',
  directives: [ROUTER_DIRECTIVES, NgClass],
  pipes: [TranslatePipe]
})
export class UserAccountFirstNameComponent implements OnInit {

  //TODO (code review): user account's first name is updated in real time when user types into the first name form, before even they have validated the form. How can I avoid that?
  currentUserAccount:UserAccount;
  submitted:boolean = false;

  FIRST_NAME_PATTERN = AppConstants.FIRST_NAME_PATTERN;

  getCssClasses = this.stylingService.getCssClasses;
  isSuccessFeedback = this.stylingService.isSuccessFeedback;
  isErrorFeedback = this.stylingService.isErrorFeedback;


  constructor(private userAccountService:UserAccountService,
              private stylingService:StylingService,
              private router:Router) {
  }

  ngOnInit() {
    this.userAccountService.currentUserAccount$.subscribe({
      next: (param)=>this.currentUserAccount = param
    });
  }

  updateFirstName(firstNameForm:ControlGroup) {
    this.submitted = true;
    if (firstNameForm.valid) {
      this.userAccountService.updateFirstName(this.currentUserAccount);
      this.router.navigate(['/dashboard/useraccount']);
    }
  }

}

组件模板如下:

<h4>{{'FIRST_NAME_FORM.TITLE' | translate}}</h4>
<form (ngSubmit)="updateFirstName(firstNameForm)" #firstNameForm="ngForm" novalidate>
    <div class="form-group" [ngClass]="getCssClasses(firstNameForm, firstName)">
        <div class="input-group">
            <span class="input-group-addon">
               <span class="glyphicon icon-account" aria-hidden="true"></span>
            </span>
            <input type="text"
                   ngControl="firstName"
                   #firstName="ngForm"
                   required
                   minlength="2"
                   maxlength="35"
                   pattern_="FIRST_NAME_PATTERN"
                   [ngModel]="currentUserAccount?.firstName"
                   (ngModelChange)="currentUserAccount ? currentUserAccount.firstName = $event : null"
                   placeholder="{{'FIRST_NAME_FORM.NEW_FIRST_NAME'| translate }}"
                   class="form-control"/>
        </div>
        <span *ngIf="isSuccessFeedback(firstNameForm, firstName)" class="form-control-feedback" aria-hidden="true">
            <span class="glyphicon icon-accept" aria-hidden="true"></span>
        </span>
        <span *ngIf="isErrorFeedback(firstNameForm, firstName)" class="form-control-feedback" aria-hidden="true">
            <span class="glyphicon icon-close" aria-hidden="true"></span>
        </span>
        <div [hidden]="firstName.valid || !submitted">
            <div *ngIf="firstName?.errors?.required" class="control-label">{{'FIRST_NAME_FORM.REQUIRED'| translate}}</div>
            <div *ngIf="firstName?.errors?.minlength" class="control-label">{{'FIRST_NAME_FORM.MIN_LENGTH'| translate}}</div>
            <div *ngIf="firstName?.errors?.maxlength" class="control-label">{{'FIRST_NAME_FORM.MAX_LENGTH'| translate}}</div>
            <div *ngIf="firstName?.errors?.pattern" class="control-label">{{'FIRST_NAME_FORM.PATTERN'| translate}}</div>
        </div>
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary pull-right" [disabled]="buttonDisabled">{{'FIRST_NAME_FORM.SUBMIT'| translate}}</button>
        <a [routerLink]="['/dashboard/useraccount']" class="btn btn-link pull-right text-right">{{'FORM_CANCEL' | translate}}</a>
    </div>
</form>

有人可以帮忙吗?

您似乎在混合使用新旧形式。

如果你使用

bootstrap(AppComponent, [
   disableDeprecatedForms()
   provideForms()
])

不要从

导入表单内容
import {ControlGroup, ...} from "@angular/common";

而是从 @angular/forms

导入它

另见