Angular 6 BehaviorSubject с использованием LocalStorage
У меня проблема с сохранением данных после обновления страницы. Я использую общий сервис для передачи данных между несвязанными компонентами. Я искал по всему Google о LocalStorage и о том, как его использовать, и я не получил ответа. Есть так много разных реализаций LocalStorage, что я не знаю, что подходит для моего проекта. У меня есть компонент детализации курса, который передает идентификатор курса службе, и компонент курса, который получает этот идентификатор и запрашивает http, получаемый с этим идентификатором. каждый раз, когда я обновляю страницу курса, данные исчезают. Мне нужна помощь с тем, что писать и где при использовании LocalStorage, чтобы сохранить эти данные после обновления (и обновить идентификатор, когда я нахожусь в другом курсе). Я приложу соответствующий код:
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));
}
}
Конечно, 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
);
}
}
Конечно, 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
);
}
}
1 ответ
Прежде всего, у вас есть ошибка в setId()
Метод - он должен иметь значение идентификатора курса в качестве аргумента, а не субъект.
Вам нужно обновить локальное хранилище сразу после вызова next()
по теме и перезагрузите сохраненные данные из хранилища в конструктор сервиса. Например,
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) || {};
}
}
Вы можете сохранить свои данные в localstorage следующим образом:
localStorage.setItem('имя переменной', JSON.stringify('данные, которые вы хотите сохранить'));
и получить данные из localstorage следующим образом:
this.anyvariable= JSON.parse(localStorage.getItem('savedvariablename'));
вот и все о локальном хранилище: