Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typeahead async results don't show since 5.5.0 (because of re-filtering) #5624

Closed
adrienverge opened this issue Jan 29, 2020 · 15 comments · Fixed by #5651
Closed

Typeahead async results don't show since 5.5.0 (because of re-filtering) #5624

adrienverge opened this issue Jan 29, 2020 · 15 comments · Fixed by #5651

Comments

@adrienverge
Copy link
Contributor

Hello,

Since yesterday (release 5.5.0), typeahead async suggestions don't show up anymore. With version 5.4.0, everything works fine. I highly suspect commit 8378105 / PR #3728.

Angular version: 8.2.11
Bootstrap version: 3.4.1

Plunker/StackBlitz that reproduces the issue: I spent 20 minutes trying to make one, but the Plunker fails with (SystemJS) XHR error (404) loading https://unpkg.com/rxjs/operators.js, and I can't use StackBlitz for 5+ minutes without it crashing. But the bug is easy to describe:

<input [(ngModel)]='searchText' [typeahead]='suggestions$' />
import {Component} from '@angular/core';
import {Observable, Observer, from} from 'rxjs';
import {switchMap} from 'rxjs/operators';

export class AppComponent  {
  searchText: string = '';
  suggestions$!: Observable<string[]>;

  ngOnInit() {
    this.suggestions$ = Observable.create((observer: Observer<string>) => {
      observer.next(this.searchText);
    })
    .pipe(switchMap((query: string) =>
      from(new Promise(r => setTimeout(() => r(['1', '2']), 500)))
    ));
  }
}

Expected behavior (works with 5.4.0): typeahead suggestions [1, 2] are shown.
Actual behavior with 5.5.0: suggestions are not shown.

@IraErshova
Copy link
Contributor

@adrienverge Hi! First of all in your code above you missed typeaheadAsync property. It has to be:

<input [(ngModel)]='searchText' [typeahead]='suggestions$' [typeaheadAsync]="true">

Also, This code is enough to create Observable:

this.suggestions$ = from(new Promise(r => setTimeout(() => r(['1', '2']), 500)));

Could you check my StackBlitz example, please?

@adrienverge
Copy link
Contributor Author

Hey Irina, thanks for your fast answer! I already tried typeaheadAsync, but it didn't change anything so I did not include it in the example (to simplify).

The problem is that since 5.5.0, it's not possible to do the search/filtering ourselves, like it was possible before (from version 1 to 5.4.0).

Said differently, this code example (that was copied-pasted from a previous doc version, probably in 2016) doesn't work anymore with 5.5.0 because ngx-bootstrap re-filters items after we've already filtered them:

this.suggestions$ = Observable.create((observer: Observer<string>) => {
  // Runs on every search:
  observer.next(this.searchText);
})
.pipe(switchMap((query: string) =>
  from(
    // Returns already-filtered results from an optimized search:
    this.myService.searchItems(query, 'ascending', 20)
    // ↑
    //  all these should be displayed, they shouldn't be re-filtered by ngx-bootstrap
  )
));

I hope this is clear, please let me know what you think.

@IraErshova
Copy link
Contributor

@adrienverge okay, let me check

@IraErshova
Copy link
Contributor

@adrienverge if I understand you correctly, your initial data is an empty array and you send request to get data from your server on every search. Correctly? I've checked such case and it works as expected. Could you please give me more information?

@adrienverge
Copy link
Contributor Author

adrienverge commented Jan 30, 2020

@IraErshova thanks for following this up. Yes, you perfectly describe our use-case!

To show the problem, I adapted your last StackBlitz (that fetched a list from https://gorest.co.in/...?first_name=xyz), so that results don't always contain the searched string. For example, searching "Nicolette Boyle" finds 1 result, but returns an object like {id: 123, phone: "+7123456"}.

In that case, it seems that ngx-bootstrap 5.5.0 re-filters results, which was not the case with 5.4.0. Since these results don't contain the initial string, none are kept.

Please see https://stackblitz.com/edit/angular-8t8dcm-puwywo:

  • with 5.4.0, searching col finds 10 results, and displays them all,
  • with 5.5.0, searching col finds 10 results, but doesn't display any.

@adrienverge adrienverge changed the title Typeahead async results don't show since 5.5.0 Typeahead async results don't show since 5.5.0 (because of re-filtering) Jan 30, 2020
@IraErshova
Copy link
Contributor

IraErshova commented Feb 3, 2020

@adrienverge Thanks for your clarification! I can see that if you enter Nicolette it returns suggestion with id and phone according to your changes. But if you enter Nicolette Boyle it doesn't return anything because of search by first_name only.

The reason why it doesn't return anything could be in your code, which processes the result of the request. Are you able to debug asyncActions method of typeahead.directive.ts with your code? Because I can't understand in what cases this issue could happen. And until we find out you can use 5.4.X

@KelseySheely
Copy link

I think there is a miscommunication here. It doesn't matter if you put in Nicolette Boyle or just Nicolette. In either case, no data displays.

You can very clearly see the issue in action if you update the stack blitz to 5.5.0 and type in Nicolette. It will show 2 Matching items, but the dropdown will not show up at all.

Note, I took out the typeaheadOptionField="first_name" from the template, but the results are the same either way.

Here's the forked Stack Blitz:

https://stackblitz.com/edit/angular-8t8dcm-kzbw52

Note that if you include typeaheadOptionField="first_name" and you include the first_name with the mapped object, it will work. However, this does not help if the whole point of the search is to do a more comprehensive search through an API, rather than being limited to a single field.

In my case, I would like to do a client search which searches first name, last name, city, etc. on the back end, as well as a concatenated first and last name. I would rather not have to create a whole new field to store all of the data that I want to search through, essentially duplicating the code that I already wrote on the back end. Is there a way to stop it from filtering after the data comes back from the Observable?

@KelseySheely
Copy link

Looks like this was broken according to the following Bug Report, but there was no discussion before implementing this breaking change.

#3725

IMO, if the user wants to filter it themselves, they should have the last word. It should absolutely not be run through the ngx filter after the user has filtered it according to what they want. Can you please roll this back or create a new directive to stop it from re-filtering.

@adrienverge
Copy link
Contributor Author

@IraErshova thanks for your reply, sorry for my late answer!

My StackBlitz example had ngx-bootstrap 5.4.0, to show that it did work before 5.5.0.
But if you try with the new version, typing "Nicolette" shows "Matching items: 2" but doesn't show any typeahead suggestion.
(Thanks @KelseySheely for the updated StackBlitz with 5.5.0.)

IMO, if the user wants to filter it themselves, they should have the last word.

I agree with @KelseySheely. It was possible from version 1 (2016) to version 5.4.0, and makes sense to be able to filter results on something more complex than just text in one of the fields.
Example: if searching "Nicolette Boyle" returns an object like {id: 123, phone: "+7123456"} (which doesn't contain the searched string), there is no way to display this typeahead suggestion with 5.5.0.

@IraErshova
Copy link
Contributor

@KelseySheely @adrienverge Thanks for your comments! I agree with you. I'm going to roll this change back. And I'm planning to find out another way to filter data via ngx-bootstrap, so developers could filter data via our or their functionality.

IraErshova added a commit to IraErshova/ngx-bootstrap that referenced this issue Feb 7, 2020
Revert filter functionality to allow developers implement their own

Close valor-software#5624
daniloff200 pushed a commit that referenced this issue Feb 7, 2020
Revert filter functionality to allow developers implement their own

Close #5624
@KirillMetrik
Copy link

@IraErshova do you please have any estimate on when this revert will be released? Latest released version is 5.5.0 (28 Jan). We're suffering from the broken filtering too.

@Confusedfish
Copy link
Contributor

Thanks for reporting this error, I too hit upon it today after a lot of head scratching. I have needed to roll back to 5.4.0 until the next release.

@adamjhickey
Copy link

adamjhickey commented Jun 30, 2021

What was the resolution to this? Was there no 5.5.1?

@KelseySheely
Copy link

KelseySheely commented Jun 30, 2021

@adamjhickey I believe the revert commit was included in 5.6.0, so anything in 5.5.* will have the bug.

https://github.com/valor-software/ngx-bootstrap/releases/tag/v5.6.0

@adamjhickey
Copy link

adamjhickey commented Jun 30, 2021

@adamjhickey I believe the revert commit was included in 5.6.0, so anything in 5.5.* will have the bug.

https://github.com/valor-software/ngx-bootstrap/releases/tag/v5.6.0

Thank you. I thought 5.6.0 was not compatible but I just had to update some imports to the more specific paths... but now dropdown alignment and z-index issues with modals appear. Probably just use a custom typeahead at this point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants