Angular 7-使用护罩时,垫子选择输入有时无法打开

时间:2019-04-06 13:54:58

标签: angular angular-material ngrx angular-guards

我从Angular中的多个应用程序结构入手,发现在Angular Material的mat-select上有奇怪的行为...

我无法打开下拉菜单-没有出现叠加层,并且调度了正常的click事件,而不是使用e.preventDefault打开材料。要检查此行为,我使用(单击)处理程序来记录事件。

如果有效-没有事件日志(调用e.preventDefault,请选择正常打开的叠加层) 如果没有,请点击事件已记录-用户界面上的任何更改

所以...首先,我检查了这可能是重大问题,因此我切换到NG-Zorro-从angular.io框架推荐,并且仍然相同...

经过数小时的调试,测试和搜索,我发现AuthGuard存在问题-仍然不知道为什么,但是让我首先描述身份验证流程。

着陆页->使用Google登录并重定向到App->授权在init(在app.component中)上分派的动作(ngrx)-> ngrx效果并监视gapi令牌并分派auth成功动作->效果并调用用于用户数据的api->登录成功。

我准备了此auth.effect进行测试

@Effect()
  authorize$: Observable<Action> = this.actions$.pipe(
    ofType(ActionTypes.Authorize),
    switchMap(() => this.authService.authState.pipe(
      map(user => {
        return user
          ? new AuthorizeSuccess(user)
          : new AuthorizeFailed();
      }),
      catchError(() => of(new AuthorizeFailed()))
    ))
  );

  @Effect()
  authorizeSuccess$: Observable<any> = this.actions$.pipe(
    ofType(ActionTypes.AuthorizeSuccess),
    switchMap((action: { type: string; payload: any }) => this.httpClient.get(`${environment.apiServerUrl}/users/me`)
      .pipe(take(1), map(response => {
        const user = new User(response ? { ...action.payload, ...ConvertingService.removeEmptyObjectValues(response) } : action.payload);
        return new LoginSuccess(user);
      }))
    ),
    tap(() => setTimeout(() => this.preloaderService.setInfinitely(true, false), 100)),
    catchError(() => of(new LoginFailed()))
  );

因此您可以看到操作流程。

Auth.reducer

export interface AuthenticationState {
  authorized: boolean
  profile: AuthUser
  user: User
}

export const initialState: AuthenticationState = {
  authorized: false,
  profile: null,
  user: null
};

export function authenticationReducer(
  state = initialState,
  action: Union
): AuthenticationState {
  switch (action.type) {

    case ActionTypes.AuthorizeSuccess:
      return {
        ...state,
        profile: action.payload
      };

    case  ActionTypes.LoginSuccess:
      return {
        ...state,
        user: action.payload,
        authorized: true
      };

   ...

    default:
      return state;
  }
}

和简单的选择器

export interface AppState {
  auth: AuthenticationState;
  router: RouterReducerState<RouterStateUrl>;
}

export const reducers: ActionReducerMap<AppState> = {
  auth: authenticationReducer,
  router: routerReducer
};

// SELECTORS
export const selectAuth = (state: AppState) => state.auth;
export const selectRouter = (state: AppState) => state.router;
export const authState = createSelector(selectAuth, (state) => state.profile);
export const authorized = createSelector(selectAuth, (state) => state.authorized);
export const currentUser = createSelector(selectAuth, (state) => state.user);

最后的保护措施,除了等待用户加载外,什么也不做

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private store: Store<AppState>) { }

  canActivate(): Observable<boolean> {
    return this.checkStore().pipe(
      switchMap(() => of(true)),
      catchError(() => of(false))
    );
  }

  private checkStore(): Observable<boolean> {
    return this.store.pipe(
      select(authorized),
      filter(authenticated => authenticated),
      take(1)
    );
  }
}

这已添加到使用的路由中

{
    canActivate: [AuthGuard],
    loadChildren: './modules/home/home.module#HomeModule',
    path: 'home',
},

所以...一切对我来说都很好(如果有人对此代码有任何好的实践-任何反馈都很好:))。但是,当我运行此代码并刷新页面选择器时,有时需要工作。好的,大部分时间。但是,当我登陆然后登录时,登录后我被重定向到页面,似乎一切正常。问题仅在我登录后直接调用此路由时出现。

请参见下面的动画 enter image description here

另一条轨迹是,当我只是return true在那个后卫中,或使其与之尽可能相似时(例如,使用一些延迟管道或奇怪的东西),当我将其映射为true时,它可以工作。但是有了预期的检查就不会了。

我将非常感谢您提出任何建议,因为我在过去的4天中都花了大量时间进行重构,测试和调试:(

这是示例项目https://github.com/wojtek1150/mat-select-error

的回购

问候,W

1 个答案:

答案 0 :(得分:2)

this._authState.next(this.getProfile(r.id_token))更改为this.ngZone.run(() => this._authState.next(this.getProfile(r.id_token)));

您需要将lambda传递给ngZone