The functionality "this.actions$.pipe" does not work due to the undefined value of actions$.
TypeError: Cannot read properties of undefined (reading 'pipe') at note.effects.ts:17:19 at createEffect (ngrx-effects.mjs:85:47) at <instance_members_initializer> (note.effects.ts:16:16) at new _NoteEffects (note.effects.ts:11:3) at Object.NoteEffects_Factory [as factory] (note.effects.ts:61:6) at core.mjs:3132:35 at runInInjectorProfilerContext (core.mjs:866:5) at R3Injector.hydrate (core.mjs:3131:11) at R3Injector.get (core.mjs:3005:23) at injectInjectorOnly (core.mjs:1095:36)
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment.development';
import { NoteDetail } from './note-detail.model';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class NoteDetailService {
readonly url: string = environment.apiBaseUrl + '/notes';
list: NoteDetail[] = [];
formData: NoteDetail = new NoteDetail();
formSubmitted: boolean = false;
constructor(private http: HttpClient) {}
refreshList(): Observable<NoteDetail[]> {
return this.http.get<NoteDetail[]>(this.url);
}
}
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { NoteDetailService } from '../../note-detail.service';
import * as NoteActions from './note.actions';
import { NoteDetail } from '../../note-detail.model';
import { Actions, createEffect, ofType } from '@ngrx/effects';
@Injectable()
export class NoteEffects {
constructor(
public actions$: Actions, // actions$ undefined value
public noteService: NoteDetailService // noteService undefined value
) {}
loadNotes$ = createEffect(() =>
this.actions$.pipe(
ofType(NoteActions.loadNotes),
mergeMap(() =>
this.noteService.refreshList().pipe(
map((notes: NoteDetail[]) => NoteActions.loadNotesSuccess({ notes })),
catchError((error) => of(NoteActions.loadNotesFailure({ error })))
)
)
)
);
main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { AppComponent } from './app/app.component';
import { provideRouter } from '@angular/router';
import { routes } from './app/app.routes';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ToastrModule } from 'ngx-toastr';
import { importProvidersFrom, isDevMode } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideStore } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import { noteReducer } from './app/store/note.reducer';
import { NoteEffects } from './app/store/note.effects';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(),
importProvidersFrom(CommonModule),
importProvidersFrom(BrowserAnimationsModule),
importProvidersFrom(ToastrModule.forRoot()),
provideStore({ notes: noteReducer }),
provideEffects([NoteEffects]),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
],
}).catch((err) => console.error(err));
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Store } from '@ngrx/store';
import { FormsModule } from '@angular/forms';
import { NgForm } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { CommonModule } from '@angular/common';
import { addNote, updateNote } from '../../store/note.actions';
@Component({
selector: 'app-note-details-form',
standalone: true,
imports: [FormsModule, CommonModule],
templateUrl: './note-details-form.component.html',
styleUrl: './note-details-form.component.scss',
})
export class NoteDetailsFormComponent {
@Input() formData = { id: 0, noteText: '' };
@Output() submit = new EventEmitter<any>();
formSubmitted: boolean = false;
constructor(private store: Store, private toastr: ToastrService) {}
onSubmit(form: NgForm) {
this.formSubmitted = true;
if (form.valid) {
if (this.formData.id === 0) this.insertRecord(form);
else this.updateRecord(form);
}
}
insertRecord(form: NgForm) {
this.store.dispatch(addNote({ note: this.formData }));
this.resetForm(form);
this.toastr.success('Inserted successfully', 'Note Detail Register');
}
updateRecord(form: NgForm) {
this.store.dispatch(updateNote({ note: this.formData }));
this.resetForm(form);
this.toastr.info('Updated successfully', 'Note Detail Register');
}
resetForm(form: NgForm) {
form.resetForm();
this.formData = { id: 0, noteText: '' };
}
}
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment.development';
import { NoteDetail } from './note-detail.model';
import { NgForm } from '@angular/forms';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class NoteDetailService {
private url: string = environment.apiBaseUrl + '/notes';
list: NoteDetail[] = [];
formData: NoteDetail = new NoteDetail();
formSubmitted: boolean = false;
constructor(private http: HttpClient) {}
refreshList(): Observable<NoteDetail[]> {
console.log(this.http.get<NoteDetail[]>(this.url));
return this.http.get<NoteDetail[]>(this.url);
}
postNoteDetail(note: NoteDetail): Observable<any> {
return this.http.post(this.url, note);
}
putNoteDetail(note: NoteDetail): Observable<any> {
return this.http.put(this.url + '/' + note.id, note);
}
deleteNoteDetail(id: number): Observable<any> {
return this.http.delete(this.url + '/' + id);
}
resetForm(form: NgForm) {
form.form.reset();
this.formData = new NoteDetail();
this.formSubmitted = false;
}
}
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NoteDetailsFormComponent } from './note-details-form/note-details-form.component';
import { Store } from '@ngrx/store';
import { NoteState } from '../store/note.state';
import { loadNotes, deleteNote, updateNote } from '../store/note.actions';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { NoteDetail } from '../shared/note-detail.model';
@Component({
selector: 'app-note-details',
standalone: true,
imports: [CommonModule, NoteDetailsFormComponent],
templateUrl: './note-details.component.html',
styleUrls: ['./note-details.component.scss'],
})
export class NoteDetailsComponent implements OnInit {
notes$: Observable<NoteDetail[]>;
formData: NoteDetail = new NoteDetail();
constructor(private store: Store<NoteState>, private toastr: ToastrService) {
this.notes$ = this.store.select((state) => state.notes);
}
ngOnInit(): void {
this.store.dispatch(loadNotes());
}
populateForm(selectedRecord: NoteDetail) {
this.formData = { ...selectedRecord };
}
onDelete(id: number) {
if (confirm('Are you sure to delete this record?'))
this.store.dispatch(deleteNote({ id }));
}
}
I checked through DevTools what exactly is causing the problem: two values from the constructor take on undefined values, which is why the program does not work any more. Help solve this problem.
Are you sure about your constructor?
export class NoteEffects {
constructor( public actions$: Actions, public noteService: NoteDetailService) {}
...
}
or they are simple variables?
export class NoteEffects {
public actions$: Actions,
public noteService: NoteDetailService
constructor() {}
...
}
NOTE: as they are public variables you always can, after inject the service give values to the variable
//in another component
constructor(private noteEfect:NoteEfect){
this.noteEfects.actions$=...
this.noteEfect.noteService=...
}