Angular 6 ng如果不适用于NGRX Store Reducers型号

时间:2018-12-28 00:52:30

标签: redux angular6 store ngrx reducers

我是redux的新手,过去几天我一直在阅读和研究它,但是我一直到错误零和警告零的地步,但仍未实现预期的行为。

基本上,我有一个登录名,它与本地MySQL联系并返回一个json对象,从那里,我希望出现一个下拉菜单。如果他们是管理员,则他们应该在下拉菜单中看到更多选项。

再次,零错误和零警告。我不知道我在想什么。

以下是我的user.state.ts文件:

import { User } from "./models/user.models";

export interface UserState {
  readonly user: User[];
}

以下是我的user.models.ts文件:

  export interface User {
  uName: string;
  isAdmin: number;
  ts: string;
  loggedIn: boolean;
}

以下是我的user.actions.ts文件:

import { Injectable } from "@angular/core";
import { Action } from "@ngrx/store";
import { User } from "../models/user.models";

export const LOGGEDIN_USER = "[USER] LoggedIn";
export const LOGGEDOUT_USER = "[USER] LoggedOut";

export class LoggedInUser implements Action {
  readonly type = LOGGEDIN_USER;

  constructor(public payload: User) {}
}

export class LoggedOutUser implements Action {
  readonly type = LOGGEDOUT_USER;

  constructor(public payload: User) {}
}

export type Actions = LoggedInUser | LoggedOutUser;

以下是我的减速器文件:

import { Action } from "@ngrx/store";
import { User } from "../models/user.models";
import * as UserActions from "../actions/user.actions";

const initialState: User = {
  uName: "Guest",
  isAdmin: 0,
  ts: "2018-12-27 00:00:00",
  loggedIn: false
};

export function reducer(
  state: User[] = [initialState],
  action: UserActions.Actions
) {

  switch (action.type) {
    case UserActions.LOGGEDIN_USER:
      return [...state, action.payload];
    case UserActions.LOGGEDOUT_USER:
      return [...state, action.payload];
    default:
      return state;
  }
}

现在,当我的服务从API接收JSON时,我将调用一个methond,该方法将分派到存储中:

addUser(uName, isAdmin, ts, loggedIn) {
this.store.dispatch(
  new UserActions.LoggedInUser({
    uName: uName,
    isAdmin: isAdmin,
    ts: ts,
    loggedIn: true
  })
);
}

在导航栏组件中,我具有以下内容:

import { Store } from "@ngrx/store";
import { User } from "../models/user.models";
import { UserState } from "../user.state";

在班级内:

  users: Observable<User[]>;
constructor(private store: Store<UserState>) {
  this.users = store.select("user");
}

在我的导航栏中,一旦该模型的LoginIn设置为true,我会出现一个下拉菜单:

<li *ngIf="users.loggedIn" ngbDropdown class="nav-item dropdown">

我也尝试过user.loggedIn,UserActions.LoggedInUser.loggedIn等...

什么也没发生。下拉菜单一开始不可见,我认为这很好,但是登录后没有任何变化。在完成这一部分的工作后,我将对导航栏中的登录和注册按钮应用相同的逻辑,除了我将使用!users.loggedIn。

在此先感谢您-如有任何错别字或语法错误,但我很累。我已经待了几天了。

1 个答案:

答案 0 :(得分:0)

万一其他人正在经历此问题,以下是我的解决方案,而我的解决方案结尾处还有一个问题。

以下是我的“ reducers / index.ts”文件:

import { ActionReducerMap } from "@ngrx/store";
import { reducer, User } from "./user.reducer";

interface AppState {
  appReducer: User;
}

export const reducers: ActionReducerMap<AppState> = {
  appReducer: reducer
};

还导入了我的'reducers / user.reducer.ts'文件:

import * as UserActions from "../actions/user.actions";
/* use mTstamp function to calculate timestamp within typescript */
function mTstamp() {
  let d = new Date();
  let mMonth;
  if (d.getMonth() < 10) {
    mMonth = "0" + d.getMonth();
  } else {
    mMonth = d.getMonth();
  }
  let mDate;
  if (d.getDate() < 10) {
    mDate = "0" + d.getDate();
  } else {
    mDate = d.getDate();
  }
  let mHours;
  if (d.getHours() < 10) {
    mHours = "0" + d.getHours();
  } else {
    mHours = d.getHours();
  }
  let mMins;
  if (d.getMinutes() < 10) {
    mMins = "0" + d.getMinutes();
  } else {
    mMins = d.getMinutes();
  }
  let mSecs;
  if (d.getSeconds() < 10) {
    mSecs = "0" + d.getSeconds();
  } else {
    mSecs = d.getSeconds();
  }
  let mTimeStamp =
    d.getFullYear() +
    "-" +
    mMonth +
    "-" +
    mDate +
    " " +
    mHours +
    ":" +
    mMins +
    ":" +
    mSecs;
  console.log("mTimeStamp: ", mTimeStamp);
  return mTimeStamp;
}

export interface User {
  uName: string;
  isAdmin: boolean;
  ts: string;
  loggedIn: boolean;
}

const initialState: User = {
  uName: "Guest",
  isAdmin: false,
  ts: mTstamp(),
  loggedIn: false
};

export function reducer(appUserState = initialState, action): User {
  switch (action.type) {
    case UserActions.ACTION_LOGOUT:
      return {
        ...appUserState,
        uName: "Guest",
        isAdmin: false,
        ts: mTstamp(),
        loggedIn: false
      };
    case UserActions.ACTION_LOGIN:
      return {
        ...appUserState,
        uName: action.payload,
        isAdmin: action.payload,
        ts: action.payload,
        loggedIn: action.payload
      };
  }
  return appUserState;
}

index.ts文件还导入了'actions / user.actions.ts'文件:

export const ACTION_LOGIN = "LoggedIn";
export const ACTION_LOGOUT = "LoggedOut";

这是我进行登录和注销所需的全部操作。

在组件中,我的大部分逻辑都是通过服务文件运行的,该文件处理通过db登录的情况:

import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { HttpClient } from "@angular/common/http";
import { Component } from "@angular/core";
import { Store } from "@ngrx/store";
import { User } from "./reducers/user.reducer";
import { Observable } from "rxjs";
import * as UserActions from "./actions/user.actions";

@Injectable({
  providedIn: "root"
})
export class ShoppingCartValuesService {
  public shoppingCartValues = "n";
  public loginObj: any;
  public uri = "<path to some local php api>";
  user: Observable<User[]>;

  constructor(
    private http: HttpClient,
    private router: Router,
    private store: Store<any>
  ) {}

  getLogin(email, password) {
    return new Observable(observe => {
      this.http
        .get(this.uri + "?name=" + email + "&pass1=" + password)
        .subscribe(res => {
          this.loginObj = res;
          if (this.loginObj.uName != null || this.loginObj.uName !== "Guest") {
            this.loginObj.loggedIn = true;
            this.getState();
            this.updateState({
              action: UserActions.ACTION_LOGIN,
              payload: this.loginObj
            });
          }
          observe.next(res);
          this.router.navigate(["/"]);
        });
    });
  }

  getState() {
    return this.store.select("appReducer");
  }

  updateState(obj) {
    this.store.dispatch({
      type: obj.action,
      payload: obj.payload
    });
    console.log("this.loginObj from updateState: ", this.loginObj);
  }

  logout() {
    const logoutObj = {
      action: UserActions.ACTION_LOGOUT,
      payload: {
        uName: "Guest",
        isAdmin: 0,
        ts: "2018-12-28 00:00:00",
        loggedIn: false
      }
    };
    this.store.dispatch({
      type: logoutObj.action,
      payload: logoutObj.payload
    });
    this.router.navigate(["/login"]);
  }
}

如您所见,返回结果(res)时,我检查用户名是否在JSON对象中,这意味着php找到了匹配项。从那里,选择商店“ appReducer”的getState()和updateState()将更改分发到商店。

以下是导航栏的相关部分,与我试图完成的工作有关,这会导致我遇到一个问题,但请在结尾处进行

  <li *ngIf="!appUserState.loggedIn" class="nav-item">
    <a
      class="nav-link"
      data-toggle="tooltip"
      title="Register"
      id="register"
      routerLink="/register"
      ><span>Register</span></a
    >
  </li>
  <li *ngIf="!appUserState.loggedIn" class="nav-item">
    <a
      class="nav-link"
      data-toggle="tooltip"
      title="Login"
      routerLink="/login"
      id="login-btn"
      ><span>Login</span></a
    >
  </li>
  <li *ngIf="appUserState.loggedIn" ngbDropdown class="nav-item dropdown">
    <a
      ngbDropdownToggle
      class="nav-link dropdown-toggle"
      href="//:javascript"
      id="dropdown01"
      data-toggle="dropdown"
      aria-haspopup="true"
      aria-expanded="false"
      >More</a
    >
    <div ngbDropdownMenu class="dropdown-menu" aria-labelledby="dropdown01">
      <a
        class="dropdown-item"
        data-toggle="tooltip"
        title="My orders"
        routerLink="/my-orders"
        id="search-records"
        ><span>Search Records</span></a
      >
      <a
        *ngIf="appUserState.isAdmin.isAdmin != '0'"
        class="dropdown-item"
        data-toggle="tooltip"
        title="Admin search records"
        routerLink="/admin/orders"
        id="admin-search-records"
        ><span>Admin Search Records</span></a
      >
      <a
        *ngIf="appUserState.isAdmin.isAdmin != '0'"
        class="dropdown-item"
        data-toggle="tooltip"
        title="Admin products"
        routerLink="/admin/products"
        id="admin-products"
        ><span>Admin Products</span></a
      >

以下是app.module.ts文件的相关部分:

import { StoreModule } from "@ngrx/store";
import { reducers } from "./reducers/";

稍后在imports数组中:

StoreModule.forRoot(reducers, {}),

现在,这可以100%正常工作,并且错误或警告为零。但是,您可能已经注意到,我不得不在导航栏中应用一些技巧-* ngIf =“ appUserState.isAdmin.isAdmin!='0'”

为什么系统会将appUserState视为对象中的对象?换句话说,为什么它不能识别* ngIf =“ appUserState.isAdmin!='0'”-直到我看到appUserState.isAdmin就是我认为的appUserState,我才意识到它将允许评估正确,因为对象存在。当我使用控制台打开对象并在其中找到具有isAdmin属性的对象时,也就是我通过添加另一个.isAdmin

解决了该问题时

如果有人可以向我解释那个,那将是锦上添花。否则,它会正常工作,并且现在已经足够了。

预先感谢