0

Here is my code:

UtilisateursService.ts

public AllUsers:Utilisateur[]=[{ UserId:'',firstName:'', lastName:'',email:'',phoneNumber:null,roles:'',active:"false",createdBy:'',createdDate:null,lastModifiedBy:'',lastModifiedDate:null,},];

  **public userSubject = new Subject<Utilisateur[]>();**
  //userSubject2 = new Subject<Classe[]>();

  emitUsers(u:Utilisateur[]) {
    this.userSubject.next(u.slice());
        }


getAllUsers() {

           var childsdata:Utilisateur[]=[];
           firebase.database().ref("/users").orderByKey().once("value").then(function(snapshot) {
               snapshot.forEach(function(childSnapshot) {
                 childsdata.push(childSnapshot.val());
             });
           });

           this.AllUsers=childsdata;
            this.emitUsers(this.AllUsers);

           console.log("this.AllUsers = ",this.AllUsers);

  };

ListeUtilisateursComponent.ts

export class ListeUtilisateursComponent implements OnInit,OnDestroy {
  // users: Utilisateur[];
  usersSubscription: Subscription;
  displayedColumns: string[] = ['nom', 'prenom', 'email', 'role','active','actions'];
  **UserdataSource;**

  constructor(private usersService: UtilisateursService,private router: Router) { }

  ngOnInit() {
    this.usersService.userSubject.subscribe((AllUsers) => {
      **this.UserdataSource = AllUsers;**
    });


    this.usersService.getAllUsers();


    // this.UserdataSource=this.usersService.getAllUsers();
    console.log("Dans ngOnInit, this.UserdataSource ==== ",this.UserdataSource);

  }

ListeUtilisateursComponent.html

<table mat-table [dataSource]="*UserdataSource*" class="mat-elevation-z8">
  <ng-container matColumnDef="nom">
    <th mat-header-cell *matHeaderCellDef> Nom </th>
    <td mat-cell *matCellDef="let element"> {{element.lastName}} </td>
  </ng-container>

  <ng-container matColumnDef="prenom">
    <th mat-header-cell *matHeaderCellDef> Prénom </th>
    <td mat-cell *matCellDef="let element"> {{element.firstName}} </td>
  </ng-container>

  <ng-container matColumnDef="email">
    <th mat-header-cell *matHeaderCellDef> Email </th>
    <td mat-cell *matCellDef="let element"> {{element.email}} </td>
  </ng-container>

the variable AllUsers of UtilisateurService updates correctly The variable UserdataSource is always empty, it seems that the observer doesn't work. Can you help me please ?

Slooguy
  • 59
  • 1
  • 2
  • 6

2 Answers2

2

put them inside your request. this is async call your data may still not fill while you try outside of request

 getAllUsers() {
  var that=this;
  var childsdata:Utilisateur[]=[];
  firebase.database().ref("/users").orderByKey().once("value").then(function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
           childsdata.push(childSnapshot.val());
           that.AllUsers=childsdata;
           that.emitUsers(that.AllUsers);
            console.log("that.AllUsers = ",that.AllUsers);
         });
      });
 };
Slooguy
  • 59
  • 1
  • 2
  • 6
mr. pc_coder
  • 16,412
  • 3
  • 32
  • 54
  • ERROR Error: Uncaught (in promise): TypeError: Cannot set property 'AllUsers' of undefined TypeError: Cannot set property 'AllUsers' of undefined . See my comment for the complete error – Slooguy May 25 '20 at 21:33
  • 1
    You're welcome :) It says undefined because 'this' is related to function(childSnapshot) in foreach so, we changed service 's 'this' to that – mr. pc_coder May 25 '20 at 21:52
0

There are issues in service and the component. In both cases, asynchronous data is accessed synchronously.

Service

childsdata is assigned asynchronously, so this.AllUsers = childsdata; statement and other statments that depend on this.AllUsers should be within the then enclosure.

And to access member variables inside callbacks, functions defined with function keyword should be replaced with arrow functions. The meaning of this keyword in a traditional JS function denotes the scope of the function and in an arrow function denotes the class.

More details on it here: https://stackoverflow.com/a/34361380/6513921

public AllUsers: Utilisateur[] = [{ UserId: '', firstName: '', lastName: '', email: '', phoneNumber: null, roles: '', active: "false", createdBy: '', createdDate: null, lastModifiedBy: '', lastModifiedDate: null},];

public userSubject = new Subject<Utilisateur[]>();

emitUsers(u: Utilisateur[]) {
  this.userSubject.next(u.slice());
}

getAllUsers() {
  let childsdata: Utilisateur[] = [];
  firebase.database().ref("/users").orderByKey().once("value").then((snapshot) => {    // <-- arrow function here
      snapshot.forEach((childSnapshot) => {    // <-- arrow function here
        childsdata.push(childSnapshot.val());
        this.AllUsers = childsdata;
        this.emitUsers(this.AllUsers);
        console.log("this.AllUsers = ",this.AllUsers);
    });
  });
};

Component

UserdataSource is assigned asynchronously, so the console log that prints it should be within the subscription.

export class ListeUtilisateursComponent implements OnInit,OnDestroy {
  // users: Utilisateur[];
  usersSubscription: Subscription;
  displayedColumns: string[] = ['nom', 'prenom', 'email', 'role','active','actions'];
  **UserdataSource;**

  constructor(private usersService: UtilisateursService,private router: Router) { }

  ngOnInit() {
    this.usersService.userSubject.subscribe((AllUsers) => {
      this.UserdataSource = AllUsers;
      console.log("Dans ngOnInit, this.UserdataSource ==== ", this.UserdataSource);
    });
    this.usersService.getAllUsers();
  }
}

See here for more details on how to access asynchronous data: https://stackoverflow.com/a/14220323/6513921

Community
  • 1
  • 1
ruth
  • 29,535
  • 4
  • 30
  • 57