I am developing a webapp with the use of NGXS, and want to understand why I am getting this specific error. I am fetching data from an API, and want to display it on the column. Within the console log, I am able to see the proper data, but I am not able to display the data.
This is for a webapp, which is being developed by using Angular and NGXS. I did try avoiding to subscribe, and just retrieve the data asynchronously within the HTML, but then it wasn't able to find the properties defined in the model. I got the errors
Property 'name' does not exist on type 'UserInfo[]'.
Property 'email' does not exist on type 'UserInfo[]'.
@Select(UserLoginSate.getInfo) userInfo$: Observable<UserInfo[]>;
info = {};
constructor(private store: Store) {
}
ngOnInit() {
this.store.dispatch(new GetUserInfo()).subscribe(result => {
this.userInfo$ = result;
});
The model is defined with two properties:
export interface UserInfo{
name: string;
email: string;
}
I expect it to display the user info (i.e. name and email), but I am getting the error Cannot set property userInfo$ of [object Object] which has only a getter
. However, the proper data can be found in the console log.
EDIT:
Here is the state:
export class UserLoginStateModel{
info: UserInfo[];
}
@State<UserLoginStateModel>({
name: 'info',
defaults: {
userInfo: []
}
})
export class UserLoginState {
constructor(private userService: UserService) {}
@Selector()
static getInfo(state: UserLoginStateModel) {
return state.userInfo;
}
@Action(GetUserInfo)
getUserInfo({getState, setState}: StateContext<UserLoginStateModel>) {
return this.userService.fetchUserInfo().pipe(tap((result) => {
const state = getState();
setState({
...state,
userInfo: result,
});
}));
}
}
This is the part of layout, which I expect will show the data:
<nb-layout-column>
<div>
name: {{ userInfo$.name }}
<br/>
email: {{ userInfo$.email }}
</div>
</nb-layout-column>
Subscribe is not necesery:
ngOnInit() {
this.store.dispatch(new GetUserInfo())
}
It could be better if You set up userInfo as an null so if user is not logged in there will be null.
@State<UserLoginStateModel>({
name: 'info',
defaults: {
userInfo: null
}
})
When You change your @state
change @Select(UserLoginSate.getInfo) userInfo$: Observable<UserInfo[]>;
to @Select(UserLoginSate.getInfo) userInfo$: Observable<UserInfo>;
.
Template change to:
<nb-layout-column>
<div *ngIf="userInfo$ | async as userInfo">
<p>name: {{ userInfo.name }}</p>
<p>email: {{ userInfo.email }}</p>
</div>
</nb-layout-column>
You cannot display Observables and Promises with no *ngIf
statement. Thay are asynchronus.