我是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。
在此先感谢您-如有任何错别字或语法错误,但我很累。我已经待了几天了。
答案 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
解决了该问题时如果有人可以向我解释那个,那将是锦上添花。否则,它会正常工作,并且现在已经足够了。
预先感谢