Skip to content

feat(typeahead): support multiple search field values #1352

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

Open
Abrissirba opened this issue Dec 19, 2016 · 20 comments
Open

feat(typeahead): support multiple search field values #1352

Abrissirba opened this issue Dec 19, 2016 · 20 comments

Comments

@Abrissirba
Copy link

I am trying to use typeahead in a scenario where we need to filter the search result based on multiple fields. Lets say we have an object like this

[{
id: 1
name: "Stockholm",
country: "Sweden"
}, {
id: 1
name: "Gothenburg",
country: "Sweden"
}]

Then if I search on "Stock" I want the Stockholm object as result. If I search for "Swe" I want both Stockholm and Gothenburg. The matching function should therefore look for a match on both the name and country property.

@valorkin valorkin self-assigned this Dec 20, 2016
@valorkin
Copy link
Member

multi select is planned feature

@critchie
Copy link

critchie commented Dec 28, 2016

@valorkin This doesn't feel like a concern of typeahead. Instead @Abrissirba you should write a service that does this. This is based on the asynchronous example in the documentation.

public getCitiesAsObservable(token:string):Observable<any> {
  return Observable.of(
    this.citiesComplex.filter((city:any) => {
      return city.name.startsWith(token) || city.country.startsWith(token);
    })
  );
}

I use this technique searching for people when matching on first and last name.

@valorkin
Copy link
Member

@critchie elegant solution! Thank you :)

@jtweeks
Copy link

jtweeks commented Jan 3, 2017

This is very much needed, I don't think the OP wants there to be multi select, just be able to filter the drop down list by more than one field in an array of objects. He or she can then select just one from that list.

@critchie
Copy link

critchie commented Jan 3, 2017

Once you have moved beyond the simple string/array of strings comparison the typeahead really can't make any assumptions about the filtering algorithm. To do what is being requested @valorkin and company would have to make assumptions about the filtering algorithm. The first assumption that comes to mind is what relational operator to use when determining a match. Is it "name AND country" or is it "name OR country"?

Returning an Observable where you explicitly define the filtering is much cleaner IMO.

@valorkin
Copy link
Member

valorkin commented Jan 3, 2017

Or allow predicates, or configurable pipes
BTW 2ND will be available in next Typeahead version ;)

@valorkin valorkin added the WIP label Jan 19, 2017
@sanyooh
Copy link

sanyooh commented Aug 23, 2017

how is the progress on this?

@valorkin
Copy link
Member

valorkin commented Aug 23, 2017

@sanyooh nearest 2 weeks I am focused on new datepicker (available from v1.9.0)
http://valor-software.com/ngx-bootstrap/#/datepicker#examples
then merge to ng v4+ (and 5) only (1-2 days)
then I will focus on typeahead

@Steven-Garcia
Copy link

Looking forward to this, it would be great to be able to do something like in uib-typeahead, ie: typeaheadOptionField(id+', '+title)

@jschank
Copy link

jschank commented Oct 27, 2017

I have a similar problem. I have an array of objects. I would like the typeahead to allow me to specify a field to use to match, and a field to use for display, and another field to use for the value.

  • A match should return an object from my collection.
  • The input field should show the value of the 'display' property.
  • The value should be set to the value of the named 'value' property.
  • I should still be able to use a template to display any combination of properties from my objects. (This currently works fine)

Do you think that would be possible?

@YevheniiaMazur YevheniiaMazur changed the title (Typeahead): Support multiple search field values feat(typeahead): support multiple search field values Jan 16, 2018
@lavanyakomarasamy
Copy link

I am getting ERROR TypeError: Cannot read property 'startsWith' of undefined.
Can you please help me?

@bandhavya
Copy link

Search by multiple fields, Any updates on this implementation ?

@Mathachew
Copy link

I'm with @jschank in that Typeahead should be more flexible in what is matched, displayed, and used for the selected value(s).

@awaheed1
Copy link

awaheed1 commented May 8, 2019

Any updates on this?

I'm not sure if I need to open a new issue, but I was wondering if TypeAheadOptionField supports multiple strings. I'd like to display a second property in my current dropdown on the Options field:

image

The html for the dropdown:

  <div class="row">
                                                    <div class="col-lg-12">
                                                        <input name="typeahead" [(ngModel)]="asyncSelected"
                                                               [typeaheadAsync]="true" [typeahead]="dataSource"
                                                               (typeaheadLoading)="changeTypeaheadLoading($event)"
                                                               (typeaheadOnSelect)="typeaheadOnSelect($event)"
                                                               [typeaheadOptionsLimit]="7"
                                                               typeaheadOptionField="schoolName"
                                                               placeholder="Start typing School Name..."
                                                               typeaheadWaitMs="1000" class="form-control">
                                                        <div *ngIf="typeaheadLoading">Loading</div>
                                                    </div>
                                                </div>

and the way I'm binding to it from my TS component:

this.dataSource = Observable.create((observer: any) => {
            observer.next(this.asyncSelected);
        })
            .pipe(
                mergeMap((token: string) => {
                    return this.schoolService.searchSchool(token, 1).pipe(map(data => data.schools));
                })
            );
    }
    asyncSelected: string;
    typeaheadLoading: boolean;
    typeaheadNoResults: boolean;
    dataSource: Observable<any>;

    changeTypeaheadLoading(e: boolean): void {
        this.typeaheadLoading = e;
    }

    typeaheadOnSelect(e: TypeaheadMatch): void {
        this.asyncSelected = null;
        this.addSchool(e.item);
    }

My school component also has a string address property that needs to also display in the search results. Not exactly sure how I'd do it.

Also the documentation link provided above: https://valor-software.com/ng2-bootstrap/#/typeahead is broken can someone update the link?

@rickithadi
Copy link

any updates on this? 💯

@robvaneck
Copy link

I solved it doing this

  ngOnInit(): void {
    // we want the typeahead to search on email and
    // firstName + lastName... so we create a searchQuery property
    // and duplicate records
    this.storeService.users$
      .pipe(
        filter(res => res !== null),
        takeUntil(this.destroy$)
      )
      .subscribe(res => {
        // get the users by email address
        // and create a searchQuery property
        const usersByEmail = _.cloneDeep(res);
        usersByEmail.forEach(x => {
          x.searchQuery = `${x.email}`.toLocaleLowerCase().replace(/ /gi, '');
        });

        // get the users with firstName and lastName
        const usersWithFullName = _.cloneDeep(res).filter(x => x.firstName);
        usersWithFullName.forEach(x => {
          x.searchQuery = `${x.firstName}${x.lastName}`.toLocaleLowerCase().replace(/ /gi, '');
        });

        this.users = [...usersWithFullName, ...usersByEmail];
      });
  }

@mtholen
Copy link

mtholen commented Jan 7, 2021

The solution for @awaheed1 is to use a templated list.

<input [(ngModel)]="asyncSelected"
       [typeahead]="dataSource"
       [typeaheadAsync]="true"
       [typeaheadScrollable]="true"       
       [typeaheadItemTemplate]="rct"
       [typeaheadOptionField]="iFormat"
       [typeaheadOptionsInScrollableView]="10"
       (typeaheadOnSelect)="onSelect($event)"
       placeholder="Locations loaded via observable"
       class="form-control">

<!-- template for resource typeahead -->
<ng-template #rct let-rc="item">
  <div class="mb-0">
    <h5 class="m-1">{{rc.resourceRef}} - {{rc.newResourceType}}</h5>
  </div>
</ng-template>

This allows you to display multiple options with your own make-up/lay-out.
image

The problem I am facing thereafter is that the typeaheadOptionField can only display a single field from the object, it does not appear to be able to show me the exact selected result?

Now I understand I can map the two properties to a single string and have that be the search and selection criteria with the original object as a seperate property, but that doesn't seem to be an elegant solution?

ngb-typeahead allows you to use a function as the displayed value, but that doesn't seem to work on ngx-typeahead?

@burakgavaskargo
Copy link

@critchie 's answer is still valid. The update link is below:
https://valor-software.com/ngx-bootstrap/old/3.0.1/#/typeahead#async-data

@ghost
Copy link

ghost commented Dec 17, 2021

An typeaheadOptionFieldFn should be enough, so we can pass a callback receiving the items and returning the final string to search the hint with. Like this:

 <input id="username" type="text" class="form-control"
         [ngModel]="data"
          [typeahead]="users"  autocomplete="off"
          [typeaheadOptionFieldFn]="optionFieldFn"
          [typeaheadScrollable]="true">
optionFieldFn(match: TypeaheadMatch) {
  const {item} = match;
  return `${item.name}${item.surname}${item.id}`;
}

@Et3rnal
Copy link

Et3rnal commented Sep 29, 2023

typeaheadOptionField already takes function but its useless in this case as it doesn't provide any parameters

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

No branches or pull requests