重定向到相同的窗体Angular后,窗体控件保持填写状态

时间:2018-07-17 16:15:00

标签: angular

我有一个登录表单http://localhost:4200/sign-in,假设我填写了表单,然后决定进入http://localhost:4200/主页。在我的AppRouting.ts中,我有一个AuthGuard,可防止已通过 not 身份验证的用户进入首页并被重定向到“登录”页面。重定向回该表单后,它仍然像以前一样填写。因此,Angular以某种方式计算出我们将返回同一页面,因此没有理由刷新页面吗?因为如果我转到其他页面并返回登录表单,则会清除

我可以覆盖此行为吗? 我还尝试通过resetForm()方法中的@ViewChild(NgForm) userSignInForm: NgForm; 通过ngOnInit制作export const appRoutes: Routes = [ { path: '', component: MainComponent, data: { title: 'main' }, canActivate: [AuthGuardService] } ]; ,但是没有运气-我认为因为从未调用此方法,因为没有发生实际的组件重新加载。想法?

AppRouting:

    @Injectable()
export class AuthGuardService implements CanActivate {
    constructor(
        private authService: AuthService,
        private router: Router,
        private activatedRoute: ActivatedRoute
    ) { }

    canActivate(): Observable<boolean> {
        console.log('authGuard fired');

        return this.authService.isUserAuthenticated().pipe(
            map((isUserAuthenticated: boolean) => {
                if (!isUserAuthenticated) {
                    this.router.navigate(['/sign-in'], {relativeTo: this.activatedRoute});
                }
                return isUserAuthenticated;
            })
        );

    }
}

AuthGuardService:

  <div class="container">


  <form (ngSubmit)="onSubmit(userSignInForm)" #userSignInForm="ngForm" class="userSignInContainer">
    <mat-card>
      <mat-card-title>Sign-in</mat-card-title>

      <mat-form-field>
        <input matInput placeholder="email" type="email" [email]="true" [(ngModel)]="loginData.Email" name="Email" required>
      </mat-form-field>

      <mat-form-field>
        <input matInput type="password" placeholder="password" [(ngModel)]="loginData.Password" name="Password" required>
      </mat-form-field>

      <mat-error *ngIf="!loginOrPassValid">{{errorMessage}}</mat-error>

      <mat-card-actions>
        <button mat-raised-button color="primary" type="submit" [disabled]="!userSignInForm.valid">sign-in</button>
      </mat-card-actions>

    </mat-card>
  </form>


</div>

HTML(表单):

{{1}}

2 个答案:

答案 0 :(得分:2)

您刚刚发现了Angular的行为:如果仍然需要更改URL,则不会破坏和重新创建组件。

例如,假设您有一个组件PersonalInfoComponent,该组件根据url中指定的ID显示用户的个人信息。如果您看到ID为 14 的用户访问/user/14的信息,然后转到/user/15,则由于性能原因该组件将不会被破坏和重新创建,因此必须使用ActivatedRoute可观察到的网址来检查网址是否更改。

这里发生的事情非常相似。首先,让我解释一下服务器端路由与客户端路由之间的区别,以便更清楚地说明实现此技巧的原因。

服务器端路由中,页面的内容由于HTTP请求而发生更改。浏览器不知道该页面的内容,也无法对其进行任何预测。

客户端路由中,视图由于单击而发生更改,并且在显示新内容后更新了URL。没有涉及服务器的请求,并且由于Angular确切知道目的地是什么,因此也可以避免在不需要时刷新和更新地址栏。例如,如果您从/导航到/first-page,并且/first-page包含重定向到/second-page的代码,则框架可以决定跳过中间步骤,只走从//second-page

这就是正在发生的事情。您从/sing-in转到/,后者重定向到/sign-in。因此,您从没有离开过页面。

如何覆盖此行为?您可以强制链接在服务器端代替客户端。

只需使用<a href="/">..</a>代替<a routerLink="/">..</a>

答案 1 :(得分:1)

好的。 @CristianTraìna解释了为什么表格从未刷新过。就我而言,我不想使用<a href="/">..</a>来强制重新加载,而只是使用Subject来触发formReload

解决方案:

AuthService:

在AuthService中,我添加了

public resetSignInFormOnRedirect = new Subject();

然后进入

AuthGuardService:

canActivate(){
...
this.router.navigate(['/sign-in'], {relativeTo: this.activatedRoute});
this.authService.resetSignInFormOnRedirect.next();
...
}

登录组件:

ngOnInit() {
    this.authService.resetSignInFormOnRedirect.subscribe(
          () => {
            this.userSignInForm.resetForm();
          }
        );
}