首页 > 解决方案 > 自动滚动到 Angular 模板驱动表单中的第一个错误字段

问题描述

我有一个像波纹管这样的表格,它比视口高度占用更多的空间。想象一下,第一个控件无效并且用户单击提交按钮,用户无法立即找出问题所在。所以我只想自动滚动到错误消息。

那么,有没有办法解决这个问题。

样本表格

        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Title</label>
            <div class="col-lg-3">
                <input [ngClass]="{'is-invalid': !isMovieTitleInEnglishValidated}" class="form-control" type="text"
                       [(ngModel)]="movieTitleInEnglish" (keypress)="resetValidation(TITLE)" name="englishTitle"
                       placeholder="Title in English">
                <div *ngIf="!isMovieTitleInEnglishValidated" class="invalid-feedback">
                    <span>{{movieTitleInEnglishValidateMessage}}</span>
                </div>
            </div>
        </div>

      
        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Description</label>
            <div class="col-lg-5">
                <textarea [ngClass]="{'is-invalid': !isDescriptionValidated}"
                          (keypress)="resetValidation(DESCRIPTION)" (focusout)="resetValidation(DESCRIPTION)"
                          class="form-control"  rows="5" [(ngModel)]="description"></textarea>
                <div *ngIf="!isDescriptionValidated" class="invalid-feedback">
                    <span>{{descriptionValidateMessage}}</span>
                </div>
            </div>
        </div>


        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Release Date</label>
            <div class="col-lg-5">
                    <input [ngClass]="{'is-invalid': !isReleaseDateValidated}"
                           class="form-control" id="example-date" [(ngModel)]="releaseDate" type="date" name="date"
                           (click)="resetValidation(RELEASE_DATE)" name="releaseDate">
                <div *ngIf="!isReleaseDateValidated" class="invalid-feedback">
                    <span>{{releaseDateValidateMessage}}</span>
                </div>

              <!--  <input [ngClass]="{'is-invalid': !isReleaseDateValidated}"
                       class="form-control" id="example-date" [(ngModel)]="releaseDate" type="date" name="date"
                       (click)="resetValidation(RELEASE_DATE)" name="releaseDate">-->

                <!--<input [ngClass]="{'is-invalid': !isReleaseDateValidated}" [dateFormat]="'Y-m-d'"
                       [convertModelValue]="true" class="form-control" mwlFlatpickr placeholder="Select a Date"
                       type="text" [(ngModel)]="releaseDate" (click)="resetValidation(RELEASE_DATE)"
                       [minDate]="minDate" name="releaseDate">-->
            </div>
        </div>


        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Runtime (mins)</label>
            <div class="col-lg-5">

                <input [ngClass]="{'is-invalid': !isRunTimeValidated}" class="form-control" min="0"
                       placeholder="Duration (min)" (click)="resetValidation(RUNTIME)" (keyup)="runtimeValidate()"
                       [(ngModel)]="runTime" type="number">
                <div *ngIf="!isRunTimeValidated" class="invalid-feedback">
                    <span>{{runTimeValidateMessage}}</span>
                </div>
            </div>
        </div>

        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Maturity rating</label>
            <div class="col-lg-5">
                <ng-select [ngClass]="{'is-invalid': !isMaturityRatingValidated}" [items]="maturityRating"
                           placeholder="Select Maturity" [(ngModel)]="selectedMaturityRating"
                           (click)="resetValidation(MATURITY)" ></ng-select>
                <div *ngIf="!isMaturityRatingValidated" class="invalid-feedback">
                    <span>{{maturityRatingValidateMessage}}</span>
                </div>
            </div>
        </div>


        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Director</label>
            <div class="col-lg-5">
                <ng-select [ngClass]="{'is-invalid': !isDirectorValidated}" #director [items]="directors"
                           (keyup)="directorsKeyPress()"
                           (clear)="clearDirectorsDropDown()"
                           bindValue="id" bindLabel="name"
                           [(ngModel)]="selectedDirector"
                           (click)="resetValidation(DIRECTOR)"
                           [multiple]="true"
                           [virtualScroll] = "true"
                           (scrollToEnd)="directorsOnScroll()"
                           placeholder="Select Director">
                </ng-select>
                <div *ngIf="!isDirectorValidated" class="invalid-feedback">
                    <span>{{directorValidateMessage}}</span>
                </div>
            </div>
            <div class="col-lg-2" style="margin-top: auto;margin-bottom: auto">
                <i class="fas fa-plus-circle" (click)="addDirector()"></i>
            </div>
        </div>


        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Producer</label>
            <div class="col-lg-5">
            <ng-select [ngClass]="{'is-invalid': !isProducerValidated}" #producer [items]="producers"
                       (keyup)="producersKeyPress()" bindValue="id" bindLabel="name"
                       (click)="resetValidation(PRODUCER)" (clear)="clearProducersDropDown()"
                       [(ngModel)]="selectedProducer"
                       [multiple]="true"
                       [virtualScroll] = "true"
                       (scrollToEnd)="producersOnScroll()"
                       placeholder="Select Producer"></ng-select>
                <div *ngIf="!isProducerValidated" class="invalid-feedback">
                    <span>{{producerValidateMessage}}</span>
                </div>
            </div>
            <div class="col-lg-2" style="margin-top: auto;margin-bottom: auto">
                <i class="fas fa-plus-circle" (click)="addProducer()"></i>
            </div>
        </div>

        
        <div class="form-group row">
            <label class="col-lg-2 col-form-label">Cast</label>
            <div class="col-lg-9">
                <ng-select [ngClass]="{'is-invalid': !isCastValidated}" #cast [items]="casts"
                           (keyup)="castsKeyPress()" (clear)="clearCastDropDown()"
                           (click)="resetValidation(CAST)"
                           [multiple]="true" bindValue="id" bindLabel="name"
                           [(ngModel)]="selectedCastMembers"
                           [virtualScroll] = "true"
                           (scrollToEnd)="actorsOnScroll()"
                           placeholder="Select Cast Members">
                    <ng-template ng-option-tmp let-item="item" let-index="index">
                        {{item.name}}
                    </ng-template>
                </ng-select>
                <div *ngIf="!isCastValidated" class="invalid-feedback">
                    <span>{{castValidateMessage}}</span>
                </div>
            </div>
            <div class="col-lg-1" style="margin-top: auto;margin-bottom: auto">
                <i class="fas fa-plus-circle" (click)="addActor()"></i>
            </div>
        </div>
</div>
<div>
    <button class="btn btn-primary" (click)="save()">Save</button>
</div>

标签: angulartypescript

解决方案


首先,获取表单中第一个错误字段的引用,或者querySelector(".form-control.is-invalid")form元素上使用,或者@ViewChildren以编程方式获取对所有控件的引用。

然后只需使用errorElement.scrollIntoView()将元素滚动到视口中。


推荐阅读