Angular Просмотр потери данных компонента во время перезагрузки. sh с использованием BehaviorSubject. - PullRequest
1 голос
/ 25 марта 2020

Я пишу приложение Angular9 с примером использования, в котором я буферизирую данные на 3 страницах (формы вводят данные).

Затем на 4-й странице я отображаю сводку собранных данных. на трех страницах в виде текста, доступного только для чтения.

Я реализовал буферизацию данных, используя следующую статью:

https://www.infragistics.com/community/blogs/b/infragistics/posts/simplest-way-to-share-data-between-two-unrelated-components-in-angular

В которой используется BehaviorSubject

Ниже представлен мой логин службы данных c:

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Observable, BehaviorSubject, throwError } from 'rxjs';
    import { retry, catchError } from 'rxjs/operators';
    import { UserResponse } from  './user-response';

    @Injectable({
      providedIn: 'root'
    })

    export class UserService {

        //Details Page 1
        public salutation: BehaviorSubject<string>;
        public firstName: BehaviorSubject<string>;

      // Base url
      baseurl = 'https://localhost:8080/rest';

      constructor(private http: HttpClient) { }

      // Http Headers
      httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'application/json'
        })
      }

      // POST
      createUser(data): Observable<UserResponse> {
        alert('user - details = '+ data);
        return this.http.post<UserResponse>(this.baseurl + '/user', JSON.stringify(data), this.httpOptions)
        .pipe(
          retry(1),
          catchError(this.errorHandler)
        )
      }

      // Error handling
      errorHandler(error) {
         let errorMessage = '';
         if(error.error instanceof ErrorEvent) {
           // Get client-side error
           errorMessage = error.error.message;
         } else {
           // Get server-side error
           errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
         }
         console.log(errorMessage);
         return throwError(errorMessage);
      }

}

Ниже представлен мой первый компонент просмотра:

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { UserService } from '../service/user.service';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'app-details1',
  templateUrl: './details1.component.html',
  styleUrls: ['./details1.component.css']
})
export class Details1Component implements OnInit {
  salutation: string;
  firstName: string;

  constructor(private userService: UserService) { }

  ngOnInit(): void {
  }

  goToDetails2(form : NgForm) {
          this.userService.salutation = new BehaviorSubject(form.value.salutation);
          this.userService.firstName = new BehaviorSubject(form.value.firstName);
      }

}

Ниже приведен фрагмент моего финального / Компонент сводного представления

import { Component, OnInit} from '@angular/core';
import { Router } from '@angular/router';
import { UserService } from '../service/user.service';

@Component({
  selector: 'app-summary',
  templateUrl: './summary.component.html',
  styleUrls: ['./summary.component.css']
})

export class SummaryComponent implements OnInit {

       salutation: string;
       firstName: string;

  constructor(
    private router: Router,
    public userService: UserService
  ) {
   }

   ngOnInit(): void {
       this.userService.salutation.subscribe(c => { this.salutation = c; });
       this.userService.firstName.subscribe(c => { this.firstName = c; });
   }

}

На последней странице мои выдержки html выглядят следующим образом:

<form #detailsForm4="ngForm">
<div class="govuk-form-group">
  <table class="govuk-table">
    <thead class="govuk-table__head">
    <tr class="govuk-table__row"></tr>
    </thead>
    <tbody class="govuk-table__body" align="left">
    <tr class="govuk-table__row">
      <th scope="row" class="govuk-table__header">Salutation</th>
      <td class="govuk-table__cell">   {{salutation}} </td>
      <td class="govuk-table__cell"> </td>
    </tr>
    <tr class="govuk-table__row">
      <th scope="row" class="govuk-table__header">First name</th>
      <td class="govuk-table__cell">   {{firstName}} </td>
      <td class="govuk-table__cell"> </td>
    </tr>

Данные отображаются на сводной странице в том виде, как они записаны в формах на страницах 1. -3, НО данные теряются на странице refre sh или когда мой компьютер находится в спящем режиме и т. Д. c

Я прочитал о локальном и сессионном хранении и использовал его с angularjs 1 .x дней. В возрасте go я был действительно удивлен, когда данные исчезли на моем итоговом экране!

Я предполагаю, что идеальным решением будет хранение данных в хранилище на стороне клиента, когда пользователь уходит от соответствующей формы, затем извлечение данных на странице сводки.

Полагаю, когда страница сводки обновляется или отображается в первый раз, я проверю хранилище данных и покажу, существуют ли они. Если хранилище пустое, то я буду использовать данные с предыдущей страницы во время выполнения.

Пожалуйста, мне нужна помощь с наилучшим практическим и стабильным решением, которое подходит для различных браузеров и является интеллектуальным для коммерческого применения.

Кроме того, подход, который вписывается в Angular9 BehaviorSubject - rx js stack ИЛИ любые последние функции, потому что я знаю, что Angular эволюционировал с AngularJs 1.x?

Сводная информация изменяется только тогда, когда пользователь переходит обратно на любую из страниц 1-3, чтобы изменить детали формы.

Я буду признателен за любой фрагмент кода или ссылку, чтобы сохранить данные на странице сводной информации.

Большое спасибо.

1 Ответ

2 голосов
/ 25 марта 2020

Я предлагаю вам использовать localStorage в вашем SummaryComponent в хуке жизненного цикла ngOnDestroy. Он всегда установит ваши данные в localStorage, прежде чем компонент будет уничтожен из-за refre sh. Затем, когда вы пытаетесь получить данные из службы, если они будут пустыми, попробуйте получить их из localStorage.

export class SummaryComponent implements OnInit, OnDestroy {

   salutation: string;
   firstName: string;

constructor(
  private router: Router,
  public userService: UserService
) {
  }

 ngOnInit(): void {
   this.userService.salutation.subscribe(c => { this.salutation = c || localStorage.get('salutation'); });
   this.userService.firstName.subscribe(c => { this.firstName = c || localStorage.get('firstName'); });
 }

 ngOnDestroy(): void {
   localStorage.setItem('salutation', this.salutation));
   localStorage.setItem('firstName', this.firstName));
 }

}

Подобную реализацию вы можете сделать в компоненте, где установлены эти значения, и вы ожидаете, что пользователь может обновить sh страницу до go до следующей страницы.

РЕДАКТИРОВАТЬ

Извините, вы правы, что ngOnDestory не будет вызывать на странице refre sh, чтобы сделать это, вы нужно будет обработать окно: beforeunload.

  @HostListener('window:beforeunload', ['$event'])
  beforeunload($event: Event): void {
   // set localStorage here
  }  

Если вы выберете свое решение, лучшим вариантом для установки элементов в localStorage будет место, где вы устанавливаете значения для сервиса. Вероятно, это goToDetails2 метод.

goToDetails2(form : NgForm) {
          this.userService.salutation = new BehaviorSubject(form.value.salutation);
          this.userService.firstName = new BehaviorSubject(form.value.firstName);
          localStorage.setItem('salutation', form.value.salutation));
          localStorage.setItem('firstName', form.value.firstName));
      }

РЕДАКТИРОВАТЬ-2 к вашей проблеме, описанной в комментарии

Я предложу вам инициализировать BehaviorSubject непосредственно внутри службы.

@Injectable({
  providedIn: 'root'
})

export class UserService {

    //Details Page 1
    public salutation: BehaviorSubject<string> = new BehaviorSubject('');
    public firstName: BehaviorSubject<string> = new BehaviorSubject('');

А затем в пределах Details1Component установите для них значения с помощью следующих

goToDetails2(form : NgForm) {
          this.userService.salutation.next(form.value.salutation);
          this.userService.firstName.next(form.value.firstName);
          localStorage.setItem('salutation', form.value.salutation));
          localStorage.setItem('firstName', form.value.firstName));
      }
...