1

I'm trying to bind the location variable in the component to another variable in the store via selector with ngrx v13 in angular, but when I put the variable with the property in the HTML I get an error:

error message: Property 'name' does not exist on type 'Observable'

that is my code:

app.selector.ts

import { createSelector } from "@ngrx/store";

export const CurrentLocationSelector=(state:AppState) => state.currentLocation;
export const getCurrentLocation = createSelector(
    CurrentLocationSelector,
    (currentLocation: any) => {
      return [...new Set(currentLocation)];
    }
);

that is my AppState:

interface AppState{
    darktheme:boolean;
    temperatureUnit:string;
    currentLocation:any; // object with the current location
    locationAutoComplete:any[]; // array that contains the result from the autocomplete
    locationCurrentWeather:CurrentItem | null;
    Forecast5Days:ForecastItem[];
    Favorites:FavoriteItem[];
    loading:boolean;
    getData:boolean;
}

in my component i wrote: current-weather.component.html

         <div class="left">
             <span class="locationName">{{location$.name}}</span>
             <span class="date">{{currentFullDate}}</span>
             <div class="weatherDescription">
                 <img [src]="imageCurrentWeather" class="weatherIcon">
                 <div class="weatherText">{{CurrentWeather.WeatherText}}</div>
             </div>
             <h1 [innerHTML]="CurrentWeather.Temperature + ' ' + currentUnit"></h1>
         </div>

in my current-weather.component.ts I wrote

  location$ = this.store.pipe(select(CurrentLocationSelector))

3 Answers3

0

So the problem here is that you are assigning your variable location$ as an observable. This means that it is not a singular object representing your data but rather a collection of multiple values that could represent your data at any point in time. Think of it as a stream of data.

This means you need to get the value of your object a given point - usually the current point in time. To do this call .subscribe() on it to listen to the incoming observables and .select to listen to the your specific selector that contains the data you want via the following:

In your current-weather.component.ts file:

let $location;
this.store.select(CurrentLocationSelector).subscribe(location => {
  $location = location; // put a debug break point here to see your value get updated
});
CodeCheshire
  • 710
  • 1
  • 8
  • 27
  • I have try this but if i do subscribe i get an empty array without values even if i updating the location in the store. – Gal Abitbul Nov 30 '21 at 08:08
  • How are you updating your store? If it is correctly updated, you should be able to use [this extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en) to see the value in your store at any given point. – CodeCheshire Dec 01 '21 at 22:02
0

You can use async pipe because location$ is observable.

<span class="locationName">{{(location$ | async).name}}</span>

current-weather.component.html

     <div class="left">
         <span class="locationName">{{(location$ | async).name}}/span>
         <span class="date">{{currentFullDate}}</span>
         <div class="weatherDescription">
             <img [src]="imageCurrentWeather" class="weatherIcon">
             <div class="weatherText">{{CurrentWeather.WeatherText}}</div>
         </div>
         <h1 [innerHTML]="CurrentWeather.Temperature + ' ' + currentUnit"></h1>
     </div>

Reference for async pipe

Saeed Sharman
  • 765
  • 5
  • 24
0

You actually flipped the .pipe and select over :

Try this:

this.location$ = this.store.select(CurrentLocationSelector).pipe(map((location)=> {return location;}))

If the problem persists, then it's most probably because of the selector, I recommend using createFeatureSelector:

import { createFeatureSelector, createSelector } from '@ngrx/store';
import { AppState } from './app.state';
export const APP_STATE_NAME = 'app';

const getAppState =
  createFeatureSelector<AppState>(APP_STATE_NAME);

export const getLocation = createSelector(getAppState, (state) => {
  return state.currentLocation;
});
Safwen Soker
  • 35
  • 2
  • 9