3

I am trying to have filterable table. I have ListComponent like this:

export class CompanyListComponent implements OnInit {
  companies$: Observable<Company[]>;
  private searchTerms = new Subject<string>();

  constructor(private companyService: CompanyService) { }

  ngOnInit() {
    this.companies$ = this.searchTerms.pipe(
        // wait 300ms after each keystroke before considering the term
        debounceTime(300),

        // ignore new term if same as previous term
        distinctUntilChanged(),

        // switch to new search observable each time the term changes
        switchMap((term: string) => this.companyService.searchCompanies(term)),
    );
}

search(term: string): void {
    this.searchTerms.next(term);
}

And my html looks like that:

<input #searchBox type="text" class="form-control" id="search-box" (keyup)="search(searchBox.value)">

<table class="table">
  <tr *ngFor="let company of companies$ | async">
    <td>{{company.name}}</td>
  </tr>
</table>

When I am writing inside the search input, table is filtered as it should be. But when I refresh page there is no data in the table at all. It appears after I put something in the input. What should I do to get all table data when the page is loaded? I tried to just start search in ngOnInit but those tries went to nowhere.

2 Answers 2

5

If you want the chain to be initialized when you subscribe to it you can use startWith.

this.companies$ = this.searchTerms.pipe(
  debounceTime(...),
  distinctUntilChanged(),
  startWith(''),
  switchMap(...)
);
Sign up to request clarification or add additional context in comments.

4 Comments

I don't know what it means
Shouldn't start with come first in the pipe?
Sorry, I was just going to write your answer too and I was building an example which I have linked
@ExplosionPills you should combine all the answers into a single answer.
2

Change searchTerms to a ReplaySubject(1) and emit a default value in the constructor.

   private searchTerms = new ReplaySubject<string>(1);

   constructor(private companyService: CompanyService) { 
          this.searchTerms.next('');
   }

When the page refreshes the searchTerms does not emit a value until the user presses a key. This means that the companies$ does nothing until the first search term is emitted.

Using a replay subject allows you to set what the first value will be.

2 Comments

Why ReplaySubject over BehaviorSubject in this case?
@ExplosionPills that works too, and would be less code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.