2
votes

I am trying to filter some hard coded data in an Ember route which is being provided by mirage and having trouble.

Either Ember moans at my syntax (when trying to use filter on the store) or it doesn't return any data when I use findAll and then use the JS filter method on the objects.

Attempt 1 - Using findAll():

Route

export default Ember.Route.extend({
    model() {
        return {
            txSites: this.get('store').findAll('site').filter((site) => {
                return site.siteType === 'tx'; 
            })
        };
    }
}); 

Template

            <select class="form-control">
                {{#each model.txSites as |site|}}
                    <option value="{{site.id}}">{{site.name}}</option>
                {{/each}}
            </select>

Mirage endpoint

this.get('/sites', () => {    

 return {
     data: [{
         type: 'site',
         id: 1,
         attributes: {
             name: 'London',
             siteType: 'tx'
         }
     },
     {
         type: 'site',
         id: 2,
         attributes: {
             name: 'Bristol',
             siteType: 'rx'                 
         }
     }]
  }      
});

Result

Successful request: GET /sites Object {data: Array[2]}

But nothing bound to the dropdown (other calls where I'm not trying to filter the results work ok).

Attempt #2 : Using filter:

export default Ember.Route.extend({
    model() {
        return {
            txSites: this.get('store').filter('site', (site) => {
                return site.siteType === 'tx'; 
            })
        };
    }
});

Result

No call made to API

Attempt #3 : using filter

export default Ember.Route.extend({
    model() {
        return {
            txSites: this.get('store').filter('site', { siteType: 'tx' }, (site) => {
                return site.siteType === 'tx'; 
            }).then((results) => { return results })
        };
    }
});

Result

Successful request: GET /sites?siteType=tx Object {data: Array[2]}

But no data bound to the select item.

It feels like I'm missing something basic here. Using ember 2.5 and ember data 1.13.

Is there a recommended way to approach this?

EDIT:

Attempt #4 - findAll with RSVP hash:

Route

export default Ember.Route.extend({
    model() {
        return Ember.RSVP.hash({
            oneThing: this.store.findAll('oneThing'),
            anotherThing: this.store.findAll('anotherThing'),
            txSites: this.store.findAll('site').filter((site) => {
                console.log(site);
                return site.siteType === 'tx';
            })
        });
    }
});

Result

Both the calls to oneThing and anotherThing bind ok, but txSites does not.

As a further test I removed the .filter from the txSites property and this happily returns the whole dataset and binds ok (so I'm happy that it's the filter causing the problem and the binding is ok).

Attempt #5

Route

export default Ember.Route.extend({
    model() {
        return Ember.RSVP.hash({
            oneThing: this.store.findAll('oneThing'),
            anotherThing: this.store.findAll('anotherThing'),
            txSites: this.store.findAll('site')
                 .then(results => results.filter((site) => {
                    return site.siteType === 'tx'; 
                 }))
        });
    }
});

Result

No data returned, console logging the site inside the filter seems to be a promise not the result of the resolved promise.

enter image description here

2

2 Answers

7
votes

You should just filter after the 'findAll' promise resolves, like this:

model() {
    return Ember.RSVP.hash({
        oneThing: this.store.findAll('oneThing'),
        anotherThing: this.store.findAll('anotherThing'),
        txSites: this.store.findAll('site')
                 .then(results => results.filter((site) => {
                    return site.get('siteType') === 'tx'; 
                 });
    });
}

Also in the mirage you should use dasherized values, so 'site-type' instead of siteType.

0
votes

You are not returning data from your model function right. Do it like this.

model(){
    return this.get('store').findAll('site').filter((site) => {
        return site.siteType === 'tx';
    });
}

Then use it in the template as:

{{#each model as |site|}}

Update:

I would suggest you to query store instead:

this.store.query('site', { filter: { siteType: 'tx' } });

Update2:

You can filter txSites inside afterModel hook, there all promises from the model hook will be resolved.