Search code examples
javascriptangularfirebasealgoliainstantsearch

Wait to load html until a referenced js value loads from an async process?


I am loading the value of a field of a document in my Firestore database via the following process:

let currentUser = firebase.auth().currentUser;
this.afs.collection("people").doc(currentUser.uid).get().subscribe( opportunities => {
 this.items = opportunities.get("following");
});

And then I'm using this.items to filter through my instantsearch data loaded in my html. I do this by defining the following config in the js code (note that I am referencing this.items as filter.

   this.config = {
        ...environment.algolia,
        indexName: 'test',
        searchParameters: {
            disjunctiveFacetsRefinements: {
            poster: this.items
        }
        },
        routing: {
          router: historyRouter(),
          stateMapping: {
            stateToRoute({query, page}) {
              return {
                query: query,
                page: page
              };
            },
            routeToState({query, page}) {
              return {
                query: query,
                page: page
              };
            }
          }
        }
    }

Then in my html, I am referencing this config object as so:

<ais-instantsearch [config]="config">

But the problem is that the html is loading this config file before my process for defining this.items successfully completes. I get that this is because it's an async process pulling from my database, but I cannot figure out how to resolve it. I tried adding the declaration of this.config into my opportunities => {} part of the code so that it happens after I get the this.items value; however, the html still loads and then it fails because config hasn't been defined yet. What is a good approach for solving this?


Solution

  • I would recommend resolving the configuration with the async pipe.

    <ais-instantsearch [config]="config | async">
    

    This will require making this.config an observable, I'd recommend the BehaviorSubject: http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html

    private readonly config: BehaviorSubject<any> = new BehaviorSubject(undefined);
    
    # ...
    
    ngOnInit() {
        let currentUser = firebase.auth().currentUser;
        this.afs.collection("people").doc(currentUser.uid).get()
            .subscribe(opportunities => {
                let items = opportunities.get("following");
                let config = {
                    ...environment.algolia,
                    indexName: 'test',
                    searchParameters: {
                        disjunctiveFacetsRefinements: {
                            poster: items
                        }
                    },
                    routing: {
                        router: historyRouter(),
                        stateMapping: {
                            stateToRoute({ query, page }) {
                                return {
                                    query: query,
                                    page: page
                                };
                            },
                            routeToState({ query, page }) {
                                return {
                                    query: query,
                                    page: page
                                };
                            }
                        }
                    }
                };
                this.config.next(config);
            });
    }