formControlName must be used with a parent formGroup directive. You'll want to add a formGroup

时间:2022-03-02 11:25:15

异常情况描述

Angular模板出现异常情况,如下所示:

formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup

异常分析

大概的意思就是formControlName没有在formGroup里面,所以猜测应该是模板位置不正确。

代码查看

<form class="signin-container" [formGroup]="signinForm" #formDir="ngForm" (ngSubmit)="onSubmit()">
    <signin-header></signin-header>
    <signin-tab (activeTabEvent)="activated($event)" [activeTabs]="activeTabs">
        <ng-container *ngIf="activeTabs==0; else loginByPassword">
            <jc-input icon="icon-phone" class="jc-margin">
                <input jcInput formControlName="account" (input)=(hideErrorMessage())  type="text" placeholder="手机号">
                <span class="common-message" *ngIf="account.errors?.required">填个手机号呗</span>
                <span class="common-message" *ngIf="account.errors?.telephone">手机号码完善下呗</span>
            </jc-input>
            <jc-input icon="icon-captcha" class="jc-margin">
                <input jcInput formControlName="captcha"  type="text" placeholder="验证码">
                <sms [phone]="account.value" [needSendSms]="true" (captchaShowed)="showCaptcha($event)"></sms>
            </jc-input>
            <input type="hidden" class="form-control"  placeholder="密码"
                formControlName="password">
            <div class="remember">
                <input class="check-box-width"  placeholder="记住我" (change)="onChange(rememberMe, $event.target.checked)"
                ng-checked="rememberMe" formControlName="rememberMe" type="checkbox"/>
                <label >两周内免登陆</label>
                <span *ngIf="errorShow" class="error-message space">{{errorMsg}}</span>
            </div>
        </ng-container>
    </signin-tab>
    <div class="private-principle">
        未注册手机验证后自动注册,登录即代表同意<a [routerLink]="'/term/dev-term'">《开发者笔记协议》</a><a [routerLink]="'/term/privacy'">《隐私保护指引》</a>
    </div>
    <div class="signin-line">
        <div class="item-submit">
            <button class="form-control btn" type="submit" [disabled]="!signinForm.valid">登录</button>
        </div>
    </div>
    <div class="quick-login" id="quick-login">    
        <span class="item fast-login">快速登录</span>
        <a class="item" [href]="githubUrl"><i class="icon-sn-github"></i></a>
        <a class="item" [href]="wechatUrl"><i class="icon-sn-weixin"></i></a>
    </div>
    <!-- <ng-template #loginByPassword>
        <jc-input icon="icon-account" class="jc-margin">
            <input jcInput formControlName="account" type="text" placeholder="手机号/邮箱">
            <span class="common-message" *ngIf="account.errors?.required">填个手机号呗</span>
            <span class="common-message" *ngIf="account.errors?.telephone">手机号码完善下呗</span>
            <span class="common-message" *ngIf="account.errors?.email">邮箱完善下呗</span>
        </jc-input>
        <jc-input icon="icon-password" class="jc-margin">
            <input jcInput type="password"  placeholder="密码" formControlName="password">
            <span class="common-message" *ngIf="password.errors?.password">密码需要8-16位包含数字和字母</span>
        </jc-input>
        <div class="remember">
            <input class="check-box-width" (change)="onChange(rememberMe, $event.target.checked)"
            formControlName="rememberMe" type="checkbox"/>
            <label>两周内免登陆</label>
            <span *ngIf="errorShow" class="error-message space remember-item">{{errorMsg}}</span>
            <a class="forget-password" [routerLink]="'/account/password-reset'">忘记密码</a>
        </div>  
    </ng-template> -->
</form>
<ng-template #loginByPassword>
    <jc-input icon="icon-account" class="jc-margin">
        <input jcInput formControlName="account" type="text" placeholder="手机号/邮箱">
        <span class="common-message" *ngIf="account.errors?.required">填个手机号呗</span>
        <span class="common-message" *ngIf="account.errors?.telephone">手机号码完善下呗</span>
        <span class="common-message" *ngIf="account.errors?.email">邮箱完善下呗</span>
    </jc-input>
    <jc-input icon="icon-password" class="jc-margin">
        <input jcInput type="password"  placeholder="密码" formControlName="password">
        <span class="common-message" *ngIf="password.errors?.password">密码需要8-16位包含数字和字母</span>
    </jc-input>
    <div class="remember">
        <input class="check-box-width" (change)="onChange(rememberMe, $event.target.checked)"
        formControlName="rememberMe" type="checkbox"/>
        <label>两周内免登陆</label>
        <span *ngIf="errorShow" class="error-message space remember-item">{{errorMsg}}</span>
        <a class="forget-password" [routerLink]="'/account/password-reset'">忘记密码</a>
    </div>  
</ng-template>

从以上代码可以看出,模板#loginByPassword的确没有在form里面,将这段模板代码移动到form里面后,问题解决。

问题总结

即使在使用angular的模板的时候,最好将模板放在指定的位置,否则可能出现异常情况。