在两个不同的组件调用之间,服务的BehaviorSubject设置为null

时间:2019-10-29 15:59:47

标签: angular ionic4 behaviorsubject

对不起,这会很长。

我有一个登录页面,成功登录后,该页面会向UserService的BehaviorSubject提供用户的令牌,然后重定向到议程页面。

此页面列出了一些事件,如果我单击事件的卡片,则会重定向到该事件的详细信息。这两个页面由同一服务处理。此服务取决于UserService。 在第一页(列表)中,我可以获取UserService的BehaviorSubject,但是就像我在查看详细信息时将其设置为null。

这是我的页面和服务(如有必要,将其截断):

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);
      }
    }

agenda.page.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像reset。也许在evenment.page.ts上输入时创建了另一个实例,但是为什么要这样呢?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

好吧,这很棘手。

在议程(列表)页面上,我使用带有href属性的离子卡。当我点击时,将呈现详细信息,但UserService会重置。

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

我用一个名为click。的事件替换了href属性,该事件调用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);
}

如果有人有解释,我不明白为什么会这样。

至少有效!