angular - 自动滚动到 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>
解决方案
首先,获取表单中第一个错误字段的引用,或者querySelector(".form-control.is-invalid")
在form
元素上使用,或者@ViewChildren
以编程方式获取对所有控件的引用。
然后只需使用errorElement.scrollIntoView()
将元素滚动到视口中。
推荐阅读
- javascript - Deno Puppetetteer 操作系统错误 13 权限被拒绝
- javascript - 将 getElementsByClassName 与 createHTMLDocument 一起使用的问题
- html - 超出弹性项目的图像
- node.js - Elasticsearch NoLivingConnectionsError:使用 Nestjs 的问题
- django - 多个模板上的上下文变量
- ios - OurPact 如何在不监督设备的情况下获得受监督的功能?
- rust - 使用 match 匹配双字母模式
- sqlite - 从行中选择 id,如果不存在则插入它(然后检索 id)
- ms-access - 如何在 MS Access 中制作自动完成或自动过滤框?
- postgresql - 不同版本的 postgresql 中的反斜杠行为