BehaviorSubject службы имеет значение null между двумя вызовами различных компонентов - PullRequest
0 голосов
/ 29 октября 2019

Извините, это будет долго.

У меня есть страница входа в систему, которая после успешного входа в систему передает объект поведения пользователя с токеном пользователя, а затем перенаправляет на страницу повестки дня.

На этой странице перечислены некоторые события, и, если я нажму на карточку события, я перенаправлюсь на детали события. Эти две страницы обрабатываются одним и тем же сервисом. Этот сервис зависит от UserService. На первой странице (листинг) я могу взять BehaviorSubject UserService, но при переходе к деталям он устанавливается равным нулю.

Вот мои страницы и сервисы (при необходимости усекаются):

user.service.ts

    @Injectable({
      providedIn: 'root'
    })
    export class UserService {
      private baseUrl = 'http://frat/';
      private userSource = new BehaviorSubject<User>(null);
      public user$ = this.userSource.asObservable();

      constructor(private httpClient: HttpClient) { }

      login(user: User): Observable<HttpResponse<User>> {
        return this.httpClient
          .post(`${this.baseUrl}/login`, user, {
            observe: 'response'
          })
          .pipe(
            tap(async (response: HttpResponse<User>) => {
              // this.setUser(new User(response.body)); //  = new User(response.body);
          })
        );
      }

      public buildAuthorizationHeader(): string {
        return 'Basic ' + btoa(this.userSource.getValue().pseudo + ':' + this.userSource.getValue().password);
      }

      /**
       * Met à jour l'observable pour avertir les observateurs dans les composants.
       * @param user
       */
      setUser(value) {
        this.userSource.next(value);
      }
    }

evenements.service.ts

    @Injectable({
      providedIn: 'root'
    })
    export class EvenementsService {
      private baseUrl = 'http://frats/evenements';
      private user: User;
      private evenementsSource = new BehaviorSubject<Evenement[]>([]);
      private evenementSource = new BehaviorSubject<Evenement>(null);

      public evenements$ = this.evenementsSource.asObservable();
      public evenement$ = this.evenementSource.asObservable();

      constructor(private httpClient: HttpClient, private userService: UserService) {
        this.userService.user$.subscribe(user => {
          console.log('EvtSvc User : ', user);
          this.user = user;
        });
      }

      public getEvenements(): Observable<Evenement[]> {
        return this.httpClient
        .get<Evenement[]>(this.baseUrl, {
          headers: {
            Authorization: this.userService.buildAuthorizationHeader()
          }
        })
        .map((evts) => {
          return evts.map((e) => new Evenement(e));
        });
      }

      public getEvenementById(id): Observable<Evenement> {
        return this.httpClient
        .get<Evenement>(this.baseUrl + '/' + id,  {
          headers: {
            Authorization: this.userService.buildAuthorizationHeader()
          }
        })
        .map((evt) => new Evenement(evt));
      }

      public setEvenements(value) {
        this.evenementsSource.next(value);
      }

      public setEvenement(value) {
        this.evenementSource.next(value);
      }
    }

повестка дня.ts (в котором перечислены события, работает нормально)

    @Component({
      selector: 'app-agenda',
      templateUrl: './agenda.page.html',
      styleUrls: ['./agenda.page.scss'],
    })
    export class AgendaPage implements OnInit {
      private evenements: Evenement[] = [];
      public titre = 'Agenda';

      constructor(private evenementService: EvenementsService) {}

      ngOnInit() {
        this.evenementService.evenements$.subscribe(evenements => this.evenements = evenements);
      }

      ionViewDidEnter() {
        this.loadData();
      }

      loadData(event = null) {
        this.evenementService.getEvenements().subscribe(evenements => {
          this.evenementService.setEvenements(evenements);
        });

        if (isNull(event) === false) {
          event.target.complete();
        }
      }
    }

evenement.page.ts (в котором пользователь userService имеет значение null, отображаемое после щелчка по отображаемому событию в повестке дня)

    @Component({
      selector: 'app-evenement',
      templateUrl: './evenement.page.html',
      styleUrls: ['./evenement.page.scss'],
    })
    export class EvenementPage implements OnInit {
      @ViewChild('map', {read: false, static: false}) mapContainer: ElementRef;
      map: any;
      private id: number;
      private evenement: Evenement;
      private localisation: Localisation;
      public titre = 'Evénement';

      constructor(
        public route: ActivatedRoute,
        private cal: Calendar,
        private evenementService: EvenementsService,
        private launchNavigator: LaunchNavigator,
        private locSvc: LocalisationService,
        private userService: UserService
      ) { }

      ngOnInit() {
        this.id = parseInt(this.route.snapshot.paramMap.get('id'), 10);
        this.evenementService.evenement$.subscribe((evenement) => this.evenement = evenement);
      }

      ionViewDidEnter() {
        this.loadData();
      }

      loadData(): void {
        this.evenementService.getEvenementById(this.id).subscribe(evenement => {
          this.evenementService.setEvenement(evenement);
        });
      }
      ... other methods to make map and marker appear ...
    }

login.page.ts

    @Component({
      selector: 'app-login',
      templateUrl: './login.page.html',
      styleUrls: ['./login.page.scss'],
    })
    export class LoginPage implements OnInit {

      private loginForm: FormGroup;
      public titre = 'Connexion';

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

      ngOnInit() {
        this.loginForm = new FormGroup({
          login: new FormControl('', Validators.required),
          password: new FormControl('', Validators.required)
        });

        this.userService.user$.subscribe((user) => {
          console.log('Login user : ', user);
        });
      }

      login(form) {
        this.userService.login(form.value).subscribe((response) => {
          if (response.status === 200) {
            this.userService.setUser(new User(response.body));
            this.router.navigateByUrl('agenda');
          }
        },
        (error) => {
          let message;

          if (error.status === 401) {
            message = 'Vos identifiants n\'ont pas été reconnus.';
          } else {
            message = 'Une erreur a eu lieu, veuillez retenter plus tard.';
          }

          this.presentAlert(message);
        });
      }

      async presentAlert(message) {
        const alert = await this.alertController.create({
          header: 'Erreur',
          subHeader: 'Un problème a eu lieu',
          message,
          buttons: ['OK']
        });

        await alert.present();
      }
    }

Я не могу понять, почему userService похож на сброс. Может быть, при входе на evenement.page.ts создается другой экземпляр, но почему тогда?

Спасибо за помощь.

1 Ответ

0 голосов
/ 30 октября 2019

Ну, это сложно.

На странице повестки дня (листинга) я использую ионные карты с атрибутом href. Когда я нажимаю, детали отображаются, но UserService как бы сбрасывается.

<ion-card button="true" href="'evenements/' + e.id" color="light" *ngFor="let e of evenements">

Я заменил атрибут href на событие (click), которое вызывает router.navigateByUrl (event / id), и этоделает трюк!

<ion-card button="true" (onclick)="showEvent(e.id)" color="light" *ngFor="let e of evenements">
showEvent(id) {
  this.router.navigateByUrl('evenement/' + id);
}

Я не понимаю, почему это так, если у кого-то есть объяснение ....

По крайней мере, это работает!

...