Home > Mobile >  Angular wait service subscription from component?
Angular wait service subscription from component?

Time:05-26

I have a problem filling a Users autocomplete on first load.

This is my UsersService:

public users: User[] = [];

constructor(private http: HttpClient) {
    this.http.get<User[]>(environment.apiUrl   URLS.USERS).subscribe({
      next: (res) => {
        this.Users = res;
      },
      error: (err) => {
        console.log(err);
      },
    });
}

filterUsers(val: string) {
  return this.users.filter(
    (user) =>
      user.name.toLowerCase().includes(val.toLowerCase())
  );
}

I get Users[] on the service constructor because this.users is going to be used by multiple components.

On the other hand I have a component as following:

constructor(
  private fb: FormBuilder,
  public userService: UsersService) {

  this.form = this.fb.group({
    user: this.user = this.fb.control('')
  });

  this.filteredUsers = this.user.valueChanges.pipe(
      startWith(''),
      map((value: string) => this.userService.filterUsers(value))
  );
}

And the view:

<mat-form-field  appearance="outline">
    <mat-label>User</mat-label>
    <input type="text" matInput formControlName="user" [matAutocomplete]="auto">
    <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" [panelWidth]="'auto'">
        <mat-option *ngFor="let sp of filteredUsers | async" [value]="sp.name">
            {{sp.name}}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

The problem: on first load,filterUsers is executed before the http GET request is completed, so this.users is null and nothing is returned. The autocomplete is empty when focusing.

If I type anything then this.users already has value and the list is correctly displayed.

How can I set values on my autocomplete on first load?

CodePudding user response:

Finally solved with observables:

Service:

public users: User[] = [];

private subj = new BehaviorSubject('');
userObs = this.subj.asObservable();

constructor(private http: HttpClient) {
    this.http.get<User[]>(environment.apiUrl   URLS.USERS).subscribe({
      next: (res) => {
        this.Users = res;
        this.subj.next('ok');
      },
      error: (err) => {
        console.log(err);
      },
    });
}

Component:

ngOnInit(): void {
  this.userService.userObs.subscribe(x => { if (x == "ok") this.user.updateValueAndValidity(); });
}

CodePudding user response:

Instead of putting filterUsers in constructor put it into ngOnInit. ngOnInit is called after the constructor.

  • Related