Angular2滚动到具有*ngIf的元素

spe*_*bob 16 angular

我正在Angular 2中编写一个表单,用户提交表单,验证它,如果输入有任何错误,我想将用户的浏览器滚动到第一个带有"错误"类的元素

问题是,我的所有错误都使用*ngIf,如下所示:

<input type="text" [(ngModel)]="model.first_name">
<div class="error" *ngIf="errors.first_name">
    {{errors.first_name}}
</div>
Run Code Online (Sandbox Code Playgroud)

在我的提交功能

submit(){
   this.errors = this.validate();
   if(this.errors.any()){
      var errorDivs = document.getElementsByClassName("error");
      if(errorDivs.length > 0){
         errorDivs[0].scrollIntoView();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我意识到这是因为*ngIf完全从DOM中删除div并且Angular检查更改还没有机会运行.有一个聪明而干净的方法吗?

Gün*_*uer 18

不确定我完全理解你的问题.

使用如下所示的指令会使元素在errors.first_name变为真实时滚动到视图中:

<div class="error" *ngIf="errors.first_name" scrollTo>
    {{errors.first_name}}
</div>
Run Code Online (Sandbox Code Playgroud)
@Directive({ selector: '[scrollTo]'})
class ScrollToDirective implements AfterViewInit {
  constructor(private elRef:ElementRef) {}
  ngAfterViewInit() {
    this.elRef.nativeElement.scrollIntoView();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常酷的解决方案,但有没有办法在同一页面上有多个错误字段,以便它只滚动到DOM中的第一个? (2认同)
  • @RahulSingh需要重新设计我的指令,因为当条件为真时不会调用ngAfterViewInit()。您可以将条件明确地传递给指令,例如&lt;div [scrollTo] =“ errors.first_name”&gt;,然后在ScrollToDirective而不是ngAfterViewInit中添加@HostBinding('hidden')isError:boolean = false ; @Input()set scrollTo(bool cond){this.isError = cond; if(cond){this.elRef.nativeElement.scrollIntoView(); }}` (2认同)

spe*_*bob 9

这是我想出的一种方式:

创建一个帮助器类

export class ScrollHelper {
    private classToScrollTo: string = null;

    scrollToFirst(className: string) {
        this.classToScrollTo = className;
    }

    doScroll() {
        if (!this.classToScrollTo) {
            return;
        }
        try {
            var elements = document.getElementsByClassName(this.classToScrollTo);
            if (elements.length == 0) {
                return;
            }
            elements[0].scrollIntoView();
        }
        finally{
            this.classToScrollTo = null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在要使用它的组件中创建一个

private scrollHelper : ScrollHelper = new ScrollHelper();
Run Code Online (Sandbox Code Playgroud)

然后当你发现你有错误

submit(){
   this.errors = this.validate();
   if(this.errors.any()){
        this.scrollHelper.scrollToFirst("error");
   }
}
Run Code Online (Sandbox Code Playgroud)

然后推迟实际滚动,直到评估ngAfterViewChecked完毕*ngIf

ngAfterViewChecked(){
    this.scrollHelper.doScroll();
}
Run Code Online (Sandbox Code Playgroud)