Ad

Observable: Get Unique Array Values From Collection Documents

What is the best way to create a list of unique values from Firestore arrays?

Each document in the collection can have any number of categories which are written in document array "categories".

I'm trying to get all unique categories of array values to populate filtering options so I need to be sure that there is a hotel for this category. I can't use just all categories list from other collection.

Angular 8, Firestore, angularfire 2, Ionic 4

Observable:

this.hotels = afs.collection('hotels', ref => ref.where('city_id', '==', cityId).orderBy('reviews_number', 'desc')).valueChanges();

Component html:

<li *ngFor="let hotel of hotels | async">
{{ hotel.categories }}
</li>

Result:

wifi
wifi
wifi,pool,center
pool

And I can't figure out what is the best practice to get unique values from arrays to be able to populate the dropdown with all unique values options.

wifi,pool,center
Ad

Answer

To keep things cleaner, I'd suggest using a separate variable to host your dropdown values, subscribing to Firestore values and fetching out the unique values then

TYPESCRIPT:

class MyComponent {
  dropDownOptions: Array<any> = [];
  someMethod() { // only called once in the component
    this.hotels = afs.collection('hotels', ref => ref.where('city_id', '==', cityId)
      .orderBy('reviews_number', 'desc'))
      .valueChanges();
    this.hotels.subscribe((hotels) => {
      const options: Array<string> = hotels.reduce((prevValue, hotel) => {
        return [...prevValue, ...hotel.categories];
      }, []);
      
      this.dropDownOptions = options.filter(this.onlyUnique); // get unique values
    })
  }

  onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
  }

}

HTML:

<select>
  <option *ngFor="let option of dropDownOptions" value="{{option}}">
    {{ option }}
  </option>
</select>

UPDATE:

There was a typo in the HTML. I.e. the dropdownOptions should have been dropDownOptions. Fixed it. Also, I've put a Stackblitz example that demonstrates the behavior.

Ad
source: stackoverflow.com
Ad