lundi 28 mars 2016

Ember.js 2 How to filter an existing model?

I'm currently learning Ember 2, and I'm trying to figure out the best approach to stacking model filters in Ember.js (2.4.2 with CLI workflow) and Ember Data.

Specifically, I am wondering if there is a good way to apply filters to an existing route's filtered model, without overriding any filtering that the route (or other component) itself may be doing.

My problem is this:

I have log entries (model "entry") which are sorted by date and associated with a user by user ID (model "user").

Model as defined in /app/routes/index.js:

export default Ember.Route.extend({
  // ...

  model: function() {
    return Ember.RSVP.hash({
      users: this.store.findAll("user")
      entries: this.store.findAll("entry")
    });
  },

  // ...
});

Model is overwritten in /app/routes/user.js:

export default Ember.Route.extend({
  // ...

  model: function() {
    return Ember.RSVP.hash({
      users: this.store.findAll("user")
      entries: this.store.filter("entry", function(entry) {
        // ...
        return entry.get("userId") === userId;
      })
    });
  },

  // ...
});

When viewed, localhost:4200/ lists all entries, and localhost:4200/user/alice lists all entries owned by the user named "alice". Likewise, localhost:4200/user/bob lists all entries by user "bob".

I also have a filtering component that allows entries to be filtered by date.

Specifically, entries on or after a "from" date, and/or entries on or before a "to" date. These date filters need to be able to applied to both the index and user routes.

The problem comes in with the user route. I can do the following in /app/components/log-filter.js to filter by date (assume this.entries is the "entry" model passed as a template attribute from the current route):

// ...

var filtered = this.entries.store.filter("entry", function(entry) {
  var logDate = entry.get("logDate");
  return logDate >= filterDateFrom && logDate <= filterDateTo;
});

this.set("entries", filtered);

This code properly filters by "date from" and "date to", but it overrides the user name filtering when run in the user route.

The quick and dirty route would be to replicate the user name filtering in the date filter callback, but this is not DRY and it will quickly become unwieldy as more routes are added (category, location, etc.), since date filters need to be universal.

My question

  1. Is there any way to filter against an existing model, rather than always starting with the global *.store.filter("modelName", callback) collection?
  2. Is this even a good approach or is there a better, more "Ember" way of handling multiple arbitrary filters?

Any help at all is appreciated.




Aucun commentaire:

Enregistrer un commentaire