-2

i'm beginner in angular framework and ionic.

i create an project to pharmacies using ionic 4 and angular...

but when i try to add a pharmacy i get an error in the function onCreatePharmaG():

Property 'subscribe' does not exist on type 'void' !!

i don't understand why ??

so what i can do ?

This is my code:

Pharmacies.service.ts

import { Injectable } from '@angular/core';
import { Pharmacie } from './pharmacie.model';
import { AuthService } from '../auth/auth.service';
import { BehaviorSubject, of } from 'rxjs';
import { take, map, tap, delay, switchMap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';


interface PharmacyData{
   DateFin: string;
   dateDeb: string;
   adresse: string;
   imageUrl: string;
   telephone: number;
   nom: string;
   userId: string;
  }

@Injectable({
  providedIn: 'root'
})
export class PharmaciesService {
  private _pharmacies =  new BehaviorSubject<Pharmacie[]>([]) ;

  get pharmacies(){
    return this._pharmacies.asObservable();
  }

  constructor(private authService: AuthService,
    private http: HttpClient
    ) { }

  fetchPharmacies(){
    return this.http.get<{[key: string]: PharmacyData}>('https://pharmacies.firebaseio.com/pharmacies.json').pipe(map(resData => {
    const pharmacies = [];
    for(const key in resData){
      if(resData.hasOwnProperty(key)){
        pharmacies.push(new Pharmacie(key,
          resData[key].nom,
          resData[key].adresse,
          resData[key].imageUrl,
          resData[key].telephone,
          new Date(resData[key].dateDeb),
          new Date(resData[key].DateFin),
          resData[key].userId));
      }
    }
    return pharmacies;
    // return [];
    }),
    tap(pharmacies => {
      this._pharmacies.next(pharmacies);
    })
    );
  }

  getPharmacy(id: string){
  return this.http.get<PharmacyData>(`https://pharmacies.firebaseio.com/pharmacies/${id}.json`
   ).pipe(map(pharmacyData => {
    return new Pharmacie(id,
      pharmacyData.nom,
      pharmacyData.adresse,
      pharmacyData.imageUrl,
      pharmacyData.telephone,
      new Date(pharmacyData.dateDeb),
      new Date(pharmacyData.DateFin),
      pharmacyData.userId);
   }));
  }

  AddPharmacyy(
   nom: string,
   adresse: string,
   telephone: number,
   dateDeb: Date,
   DateFin: Date){
     let generatedId: string;
     let newPharmacy: Pharmacie;
     this.authService.userId.pipe(take(1), switchMap(userId => {
      if(!userId){
        throw new Error('id non trouvé !');
      }
       newPharmacy = new Pharmacie(
       Math.random().toString(),
        nom,
        adresse,
        'https://cdn.1min30.com/wp-content/uploads/2018/05/Logo-Pharmacie-500x263.jpg',
        telephone,
        dateDeb,
        DateFin,
        userId
        );
        return this.http.post<{name: string}>('https://pharmacies.firebaseio.com/pharmacies.json', {...newPharmacy, id: null});
     }),
      switchMap(resData => {
        generatedId = resData.name;
        return this.pharmacies;
      }),
      take(1),
      tap(pharmacies => {
        newPharmacy.id = generatedId;
          this._pharmacies.next(pharmacies.concat(newPharmacy));
      })
      );
   }

   updatePharmacy(
    pharmacieId: string,
    nom: string,
    adresse: string,
    telephone: number,
    dateDeb: string,
    DateFin: string
    ){
      let updatedPharmacies: Pharmacie[];
       return this.pharmacies.pipe(
        take(1),
        switchMap(pharmacies => {
          if(!pharmacies || pharmacies.length <= 0){
           return this.fetchPharmacies; 
          }else{
            return of(pharmacies);
          }
        }),
        switchMap(pharmacies => {
          const updatedPharmacyIndex = pharmacies.findIndex(ph => ph.id === pharmacieId);
          const updatedPharmacies = [...pharmacies];
          const oldPharma = updatedPharmacies[updatedPharmacyIndex];
          updatedPharmacies[updatedPharmacyIndex] = new Pharmacie(oldPharma.id, nom, adresse, oldPharma.imageUrl, telephone, oldPharma.dateDeb, oldPharma.DateFin, oldPharma.userId);
          return this.http.put(
            `https://pharmacies.firebaseio.com/pharmacies/${pharmacieId}.json`,
            { ...updatedPharmacies[updatedPharmacyIndex], id: null}
            );
        }),
        tap(() =>{
        this._pharmacies.next(updatedPharmacies);
        }));   
    }

   cancelPharmacy(pharmacieId: string){
    return this.http.delete(`https://pharmacies.firebaseio.com/pharmacies/${pharmacieId}.json`).pipe(
      switchMap(() => {
      return this.pharmacies;
      }),
      take(1),
      tap(pharmacies => {
         this._pharmacies.next(pharmacies.filter(pha => pha.id !== pharmacieId));
       })
      );
   }
   
}

add-pharamcie.page.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { PharmaciesService } from '../../pharmacies.service';
import { Router } from '@angular/router';
import { LoadingController } from '@ionic/angular';

@Component({
  selector: 'app-ajouter-pharmacie',
  templateUrl: './ajouter-pharmacie.page.html',
  styleUrls: ['./ajouter-pharmacie.page.scss'],
})
export class AjouterPharmaciePage implements OnInit {
  form: FormGroup;

  constructor(
    private pharmaciesService: PharmaciesService,
    private router: Router,
    private loadingCtrl: LoadingController
  ) { }

  ngOnInit() {
    this.form = new FormGroup({
      nomPha: new FormControl(null, {
        updateOn: 'blur',
        validators: [Validators.required]
      }),
      AdrPha: new FormControl(null, {
        updateOn: 'blur',
        validators: [Validators.required, Validators.maxLength(180)]
      }),
      numPharmacie: new FormControl(null, {
        updateOn: 'blur',
        validators: [Validators.required, Validators.min(1)]
      }),
      dateDebut: new FormControl(null, {
        updateOn: 'blur',
        //validators: [Validators.required]
      }),
      dateFin: new FormControl(null, {
        updateOn: 'blur',
        // validators: [Validators.required]
      })
    });
  }

  onCreatePharmaG(){
    if(!this.form.valid){
      return;
    }
    this.loadingCtrl.create({
      message: 'Création d\'une pharmacie...'
    }).then( loadingEl => {
    loadingEl.present();
    this.pharmaciesService.AddPharmacyy(
      this.form.value.nomPha,
      this.form.value.AdrPha,
      +this.form.value.numPharmacie,
      new Date(this.form.value.dateDebut),
      new Date(this.form.value.dateFin)
      ).subscribe(() => {
        loadingEl.dismiss();
        this.form.reset();
        this.router.navigate(['/pharmacies/syndicat']);
      });
    });
  }

}

Syndicat.page.ts

import { Component, OnInit } from '@angular/core';
import { Pharmacie } from '../pharmacie.model';
import { PharmaciesService } from '../pharmacies.service';
import { IonItemSliding, LoadingController } from '@ionic/angular';
import { Subscription } from 'rxjs';
import { Router } from '@angular/router';

@Component({
  selector: 'app-syndicat',
  templateUrl: './syndicat.page.html',
  styleUrls: ['./syndicat.page.scss'],
})
export class SyndicatPage implements OnInit {
  pharmacies: Pharmacie[];
  isLoading = false;
  // listedLoadedPharmacies: Pharmacie[];
  private pharmaciesSub: Subscription;

  constructor(private pharmaciesService: PharmaciesService,
    private router: Router,
    private loadingCtrl: LoadingController) { }


  ngOnInit() {
    this.pharmaciesSub= this.pharmaciesService.pharmacies.subscribe(pharmacies =>{
    this.pharmacies = pharmacies;
    // this.listedLoadedPharmacies = this.loadedPharmacies.slice(1);
    });
  }

  ionViewWillEnter(){
    this.isLoading = true;
    this.pharmaciesService.fetchPharmacies().subscribe(() => {
      this.isLoading = false;
    });
  }
 
  
  onCancelPharmacy(pharmacieId: string, slidingEl: IonItemSliding){
    slidingEl.close();
    this.loadingCtrl.create({message: 'Suppression...'}).then(loadingEl => {
      loadingEl.present();
    this.pharmaciesService.cancelPharmacy(pharmacieId).subscribe(() => {
      loadingEl.dismiss();
    });
    });
  }

  onEdit(pharmacieId: string, slidingItem: IonItemSliding){
    slidingItem.close();
    this.router.navigate(['/', 'pharmacies', 'liste-pharmacies', 'modifier', pharmacieId ]);
   // console.log('Editing item', pharmacieId);
  }

  ngOnDestroy(){
    if(this.pharmaciesSub){
      this.pharmaciesSub.unsubscribe();
    }
  }


}
Modus Tollens
  • 5,083
  • 3
  • 38
  • 46
  • 1
    The variable you're calling subscribe on is undefined. That's actually pretty clear? – maio290 Mar 30 '20 at 10:39
  • 1
    Does this answer your question? [How to avoid 'cannot read property of undefined' errors?](https://stackoverflow.com/questions/14782232/how-to-avoid-cannot-read-property-of-undefined-errors) – maio290 Mar 30 '20 at 10:39
  • 1
    Will you please add the service code too?? – M A Salman Mar 30 '20 at 10:51

1 Answers1

1

The error is correct you are trying to subscribe to a value that is undefined.

Specifically, your AddPharmacyy method has a return type of void as it has no return statement.

You need to put return in front of this.authService.userId.pipe

An error like this might be in more parts of your code so be sure to check it. I'd also recommend following a best practices guidlines and also including a linter in your app to get rid of such errors.

Vojtech
  • 2,756
  • 2
  • 19
  • 29