Reputation: 671
I'm having a problem saving data after refreshing a page. I'm using a shared service to pass data between unrelated components. I searched over all Google about LocalStorage and how to use it and I didn't get an answer. there are so many different implements of LocalStorage that I don't know what fits my project. I have course-detail component which pass course id to the service, and course-play component which get that id and request http get with this id. every time I refresh course-play page the data disappear. I need help with what to write and where when using LocalStorage to save this data after refresh (and update the id when I'm in a different course). I'll attach the relevant code:
course.service
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { Observable, throwError } from 'rxjs';
import { catchError, groupBy } from 'rxjs/operators';
import { ICourse } from './course';
// Inject Data from Rails app to Angular app
@Injectable()
export class CourseService{
// JSON url to get data from
private url = 'http://localhost:3000/courses';
private courseUrl = 'http://localhost:3000/courses.json';
// Subscribe data
private courseId = new BehaviorSubject(1);
public courseId$ = this.courseId.asObservable();
// here we set/change value of the observable
setId(courseId) {
this.courseId.next(courseId)
}
constructor(private http: HttpClient) { }
// Handle Any Kind of Errors
private handleError(error: HttpErrorResponse) {
// A client-side or network error occured. Handle it accordingly.
if (error.error instanceof ErrorEvent) {
console.error('An error occured:', error.error.message);
}
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
else {
console.error(
'Backend returned code ${error.status}, ' +
'body was ${error.error}');
}
// return an Observable with a user-facing error error message
return throwError(
'Something bad happend; please try again later.');
}
// Get All Courses from Rails API App
getCourses(): Observable<ICourse[]> {
const coursesUrl = `${this.url}` + '.json';
return this.http.get<ICourse[]>(coursesUrl)
.pipe(catchError(this.handleError));
}
// Get Single Course by id. will 404 if id not found
getCourse(id: number): Observable<ICourse> {
const detailUrl = `${this.url}/${id}` + '.json';
return this.http.get<ICourse>(detailUrl)
.pipe(catchError(this.handleError));
}
}
course-detail.component
import { Component, OnInit, Pipe, PipeTransform } from '@angular/core';
import { ActivatedRoute, Router, Routes } from '@angular/router';
import { ICourse } from '../course';
import { CourseService } from '../course.service';
// Course-detail decorator
@Component({
selector: 'lg-course-detail',
templateUrl: './course-detail.component.html',
styleUrls: ['./course-detail.component.sass']
})
export class CourseDetailComponent implements OnInit {
course: ICourse;
errorMessage: string;
constructor(private courseService: CourseService,
private route: ActivatedRoute,
private router: Router) {
}
// On start of the life cycle
ngOnInit() {
// get the current course id to use it on the html file
const id = +this.route.snapshot.paramMap.get('id');
// set curretn course Id in the service to use it later
this.courseService.setId(id);
this.getCourse(id);
}
// Get course detail by id
getCourse(id: number) {
this.courseService.getCourse(id).subscribe(
course => this.course = course,
error => this.errorMessage = <any>error
);
}
}
course-play.component
import { Component, OnInit, Input} from '@angular/core';
import { ActivatedRoute, Router, Routes, NavigationEnd } from '@angular/router';
import { MatSidenavModule } from '@angular/material/sidenav';
import { ICourse } from '../course';
import { CourseService } from '../course.service';
// Couse-play decorator
@Component({
selector: 'lg-course-play-course-play',
templateUrl: './course-play.component.html',
styleUrls: ['./course-play.component.sass']
})
export class CoursePlayComponent implements OnInit {
errorMessage: string;
course: ICourse;
courseId: number;
constructor(private courseService: CourseService,
private route: ActivatedRoute,
private router: Router) {
courseService.courseId$.subscribe( courseId => {
this.courseId = courseId;
})
}
// On start of the life cycle
ngOnInit() {
// get the current segment id to use it on the html file
const segment_id = +this.route.snapshot.paramMap.get('segment_id');
console.log(this.courseId);
this.getCourse(this.courseId);
}
// Get course detail by id
getCourse(id: number) {
console.log(id);
this.courseService.getCourse(id).subscribe(
course => this.course = course,
error => this.errorMessage = <any>error
);
}
}
Upvotes: 1
Views: 8175
Reputation: 1
You can save your data into localstorage by this:
localStorage.setItem('variablename', JSON.stringify('data you want to save'));
and to get data back from localstorage by this:
this.anyvariable= JSON.parse(localStorage.getItem('savedvariablename'));
that's it about localstorage:
Upvotes: 0
Reputation: 12376
First of all, you have an error in the setId()
method - it has to have a value of the course ID as an argument and not the subject.
You need to update the local storage right after you invoke next()
on the subject, and reload the saved data from the storage in the constructor of the service. For example,
const COURSES_IN_STORAGE = 'courses_in_storage';
@Injectable()
export class CourseService{
...
courseIdState: string;
// This method is invokes by the component
setId(courseIdValue: string) {
this.courseId.next(courseIdValue);
localStorage.setItem(COURSES_IN_STORAGE, courseIdValue);
}
constructor() {
this.courseIdState = localStorage.getItem(COURSES_IN_STORAGE) || {};
}
}
Upvotes: 1