alex-okrushko on init-value
feat(component-store): remove q… (compare)
brandonroberts on component-store-schematics
brandonroberts on master
feat(component-store): add ng-a… (compare)
timdeschryver on component-store-schematics
build(component-store): add sch… (compare)
@anno1985 if the reference of the object is the same as the memoized reference it doesn't fire. So even if your state is a new reference, an object within that state {...state} will be the same reference. You need to compose your selectors, where each selector extracts a specific property. If the state changes, the composed selector will run until it hits the objectreference === memoizedobjectreference.
And yes, that is how you do it. map(id => entities[id)...
Hi, i have a few observables loaded when i init my views with simple things like the position of the cursor or the zoom applied.
On my query state i select the correspondant value from the store like this:
this.zoomLevel$ = this.store.pipe(
select(LayoutState.mapZoomLevel)
);Usually i would subscribe to the values and update a local variable with the new value from the store, but for things like the zoom level i dont really need to store it, i just pass it down to other components.
Situation has changed and i now would like to save a snapshot of the values. Basically, i just need a single object with the values, but the only way i know is to query the values, then subscribe and update local variables, which will bloat my code...
How can i get the value directly from the observable?
imports: [... StoreModule.forFeature(...) ] in its module init. In the module I'm trying to test, when I try to use the provideMockStore<State>({ initialState }), then I get an error NullInjectorError: No provider for StoreRootModule!
StoreModule.forRoot({}) to my imports then I get: WARN: '@ngrx/store: The feature name "core" does not exist in the state, therefore createFeatureSelector cannot access it. Be sure it is imported in a loaded module using StoreModule.forRoot('core', ...) or StoreModule.forFeature('core', ...). If the default state is intended to be undefined, as is the case with router state, this development-only warning mess
routerNavigatedAction from @ngrx/router-store, like this:changeRoute$ = createEffect(() =>
this.actions$.pipe(
ofType(routerNavigatedAction),
mergeMap(action =>
this.http.get("/api/someresource").pipe(map(x => myFeatureActions.load.success(x)))
)))
changeRoute$ effect is not being unsubscribed. Am I doing something wrong? Or is it a bug?
core.js:6228 ERROR TypeError: Cannot read property 'entities' of undefined
at selectEntities (entity.js:65)
at store.js:1061
at memoized (store.js:976)
at defaultStateFn (store.js:1016)
at store.js:1070
at memoized (store.js:976)
at store.js:1015
at Array.map (<anonymous>)
at defaultStateFn (store.js:1011)
at store.js:1070 -----------Reducer code -------------------------------------import {EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'
// import {BodyMap} from '@app/core'
import {BodyMapActions, BodyMapTypes} from '../actions'
export interface BodyMapState extends EntityState<any> {
loaded: boolean
loading: boolean
}
export const adapter: EntityAdapter<any> = createEntityAdapter<any>()
export const initialBodyMapState: BodyMapState = adapter.getInitialState({
loaded: false,
loading: false
})
export function bodyMapReducer(state: BodyMapState = initialBodyMapState, actions: BodyMapActions): BodyMapState {
switch(actions.type) {
case BodyMapTypes.CREATE_BODY_MAP: {
return adapter.addOne(actions.payload.bodymap, {
...state,
loading: false,
loaded: true
})
}
case BodyMapTypes.LOAD_BODY_MAPS:
break
case BodyMapTypes.LOAD_BODY_MAPS_SUCCESS:
return adapter.addAll(actions.payload, {
...state,
loaded: true,
loading: false
})
case BodyMapTypes.LOAD_BODY_MAPS_FAIL:
break
}
}
export const getBodyMapEntities = (state: BodyMapState): {[id: number]:any} => {
return state.entities;
}
export const { selectIds, selectEntities, selectAll } = adapter.getSelectors()
-----------Reducer code -------------------------------------
import {EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'
// import {BodyMap} from '@app/core'
import {BodyMapActions, BodyMapTypes} from '../actions'
export interface BodyMapState extends EntityState<any> {
loaded: boolean
loading: boolean
}
export const adapter: EntityAdapter<any> = createEntityAdapter<any>()
export const initialBodyMapState: BodyMapState = adapter.getInitialState({
loaded: false,
loading: false
})
export function bodyMapReducer(state: BodyMapState = initialBodyMapState, actions: BodyMapActions): BodyMapState {
switch(actions.type) {
case BodyMapTypes.CREATE_BODY_MAP: {
return adapter.addOne(actions.payload.bodymap, {
...state,
loading: false,
loaded: true
})
}
case BodyMapTypes.LOAD_BODY_MAPS:
break
case BodyMapTypes.LOAD_BODY_MAPS_SUCCESS:
return adapter.addAll(actions.payload, {
...state,
loaded: true,
loading: false
})
case BodyMapTypes.LOAD_BODY_MAPS_FAIL:
break
}
}
export const getBodyMapEntities = (state: BodyMapState): {[id: number]:any} => {
return state.entities;
}
export const { selectIds, selectEntities, selectAll } = adapter.getSelectors()
import { createSelector } from "@ngrx/store";
import { BodyMapState, getBodyMapEntities } from "../reducers/body-map.reducer";
import { getBodyState, BodyState } from "../reducers";
import { selectAll, selectEntities, selectIds } from "../reducers/body-map.reducer";
import { Dictionary } from "@ngrx/entity";
import { selectAllCaseEntities } from "@app/core";
export const selectBodyMapState = createSelector(
getBodyState,
(state: BodyState): BodyMapState => {
return state.bodyMap
}
)
export const selectAllEntities = createSelector(
selectBodyMapState,
selectEntities
)
export const selectBodyMapIds = createSelector(
selectBodyMapState,
selectIds
)
export const selectAllBodyMaps = createSelector(
selectBodyMapState,
selectAll
)
export const getAllBodyMapEntites = createSelector(
selectBodyMapState,
getBodyMapEntities
)
export const selectAllBodyMapEntities = createSelector(
selectAllEntities,
selectBodyMapIds,
(skeches: Dictionary<any>):any => {
const key = Object.keys(skeches)[0]
return skeches[key]
})
const basicPatientAdapter: EntityAdapter<sPatient> = createEntityAdapter<
sPatient
>({
sortComparer: (a: sPatient, b: sPatient) =>
a.Surname.localeCompare(b.Surname),
});
@derekkite
export const {
selectAll,
selectEntities,
selectIds,
selectTotal,
} = basicPatientAdapter.getSelectors();
export const patientState = (state: index.State) => state.patients;
export const getPatients = createSelector(patientState, selectEntities);I'm using getPatients, but have some post-processing to get to the dataslice that I need in a service, which is doing an rxjs map iterating like this:
map((p) => {
let arr: iSPatient[] = [];
for (let o in p) {
// much simplified
array.push(o)
}
return array
}
Hi everyone!
I have a question about ngrx and custom elements.... My app has a state and is built as a custom element. This custom element is used twice by a index.html and my problem is that the second instance of the custom element overwrite the state of the first instance.
My first thought was to use an injection token StoreModule.forRoot(REDUCER_TOKEN) when I'm definiting the main module, but the problem keeps. Any idea/clue/help is really welcome!
Hello!
Working on re-hydrating state from local storage, just one piece, the logged in user. I know there are libraries, or I could do this with a custom meta reducer but I just wanted to see if there was any reason I shouldn't just handle it in my initialState:
export const initialLoginServiceState: LoginServiceState = {
user: JSON.parse(localStorage.getItem('user')) ?? null,
};
Hi guys, i hope i can get some clarification on this.
When loading a view, i run a queryState on my constructor. As an example, take this:
this.settings$ = this.store.pipe(
select(SessionState.currentSettings)
);This means that i get the observable from the state, right?
So, on ngOnInit i subscribe to the observable and i get the settings like this:
this.settings$.pipe(takeUntil(this.destroy$))
.subscribe(settings => this.settings = settings);Even tho i'm not sure if its the best way, this worked to far for me.
Now i've been working on something else that i need to take some part of the settings (or the whole settings, it doesnt matter) on a separate function. I do it like this, inside said function:
let tempSettings;
this.settings$.pipe(take(1))
.subscribe(settings => {
tempSettings = settings.partOfSettings;
});Few assumptions that might need correction:
I now have 2 subscriptions for a brief moment. The first one keeps watching until i destroy the component and the second one finishes after taking the settings one time, am i right? Or does the second one destroy the first one on the process?
For the settings example i can get the local values that are already stored, but some other states are not needed on the view itself, just on that brief moment, hence why i'm using the take(1) approach. Is there a better way to do this? Some parts of the state wont be change during the life of the view, is there any way to get the value with something like this(which wont work), and not getting the observable but the actual value:
const temp = this.store.pipe(
select(SessionState.currentSettings)
);Thanks in advance
@nunofreitasbotelho here is what I would do.
this.settings$ = this.store.pipe(
select(SessionState.currentSettings),
tap(s => this.separatefunctionneedingstate(s)),
map(settingsstate => shape into what you need for the view),
);then in the view
{{settings$ | async}}then you don't need to unsubscribe.
Good day to all. My first try of this support system.
Is there a way to change DefaultDataServiceConfig property on an active instance of EntityCollectionServiceBase<T> ?
For example if I want to allow a user to adjust property of: timeout to a longer interval and let him re-fetch the HTTP data via get on a given entitity service.
For more details I have an un-ansewered question on StackOverflow - here
Thx