javascriptember.jsember-dataember-components

How to cache random results using Ember data?


Thanks to whoever is reading this and helping out. I'm going to describe what's already working, and then where I'm trying to get to (which I can't figure out):

What's working: In an EmberJS Component, there is a button that populates a textbox with a random string from a given collection of EmberData objects. The model() function queries for all of the objects from the API, and then the random_search() function picks a random one from the list and inserts it into the textbox. The code so far looks like this:

In componennt.js:

export default Component.extend({
  store: service('store'),
  model() {
    return this.store.findAll('randomsearchitem').then(function(items) {
      return items.map(function(item) {
        return {id: item.get('id'), funnnystory: item.get('funnystory')};
      })
    });
  },
  actions: {
    random_search() {
      this.model().then(function(items) {
        $('#searchbar-searchtext').val(items[Math.floor(Math.random() * items.length)]['id']);
        $('#searchbar-form').submit();
      });
    }
  }
}

In view.hbs:

<button onclick={{action "random_search"}}>I'm Feeling Lucky!</button>

What I want: I would like to have:

  1. model() query for 15 random objects from the API and cache them locally, persisting between page loads. The API will potentially have a list of 1000's of them and I'd like to implement this logic client-side if possible. If this were SQL the query would look something like SELECT * FROM 'randomsearchitems' LIMIT 15
  2. random_search() to select one item, use it, and then discard it from the cache
  3. Once all 15 have been used once, I want to call the API again for a new list of 15 strings
  4. Uniqueness does not have to be enforced -- if the list of new objects contains an object that was present in the previous list, that's ok

Thankss


Solution

  • I know this isn't exactly what you are asking for, but I'd have the backend provide the random 15 items, and use the following code.

    export default Route.extend({
      async model() {
        let response = await fetch('/api/whatever-endpoint');
        let json = await response.json();
    
        return { items: json };
      }
    });
    

    then, in a controller

    export default Controller.extend({
      searchText: '',
    
      actions: {
        didSubmitForm() {
          // do something here on submit
          // fetch again? add item to list?
          // depends!
        }
        search() {
          let items = this.model.items;
          let randomId = items[Math.floor(Math.random() * items.length].id
    
          $('#searchbar-searchtext').val(randomId);
          $('#searchbar-form').submit(); // or call a native function here
        }
      }
    });