Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setFilter and removeFilter #2318

Closed
cmaher opened this issue Feb 12, 2015 · 3 comments
Closed

Add setFilter and removeFilter #2318

cmaher opened this issue Feb 12, 2015 · 3 comments

Comments

@cmaher
Copy link
Member

cmaher commented Feb 12, 2015

Following up on #2261, I see a very common use case being: change your filter, and render with that new filter. To that end, I am proposing a setFilter/removeFilter pair. They would behave as follows:


To change the filter and re-render the collection view, call setFilter with the new filter function.
setFilter will not cause the view to render if

  • the view has not yet been rendered
  • the view has been destroyed
  • the new filter is the same as the existing filter
  • { preventRender: true } is passed in the options

To remove the filter, use removeFilter, which accepts the same options
as setFilter and will cause a re-render under the same conditions.

  var cv = new Marionette.CollectionView({
    childView: SomeChildView,
    emptyView: SomeEmptyView,
    collection: new Backbone.Collection([
      { value: 1 },
      { value: 2 },
      { value: 3 },
      { value: 4 }
    ]),

    // Only show views with even values
    filter: function (child, index, collection) {
      return child.get('value') % 2 === 0;
    }
  });

  // renders the views with values '2' and '4'
  cv.render();

  // removes the filter, re-renders and shows all views
  cv.removeFilter();

  // re-renders the collection view, showing the views with values '1' and '3'
  cv.setFilter(function (child, index, collection) {
    return child.get('value') % 2 !== 0;
  });

  // removes the filter, but does not re-render
  cv.removeFilter({ preventRender: false });

  // shows all views, using the new filter
  cv.render();

  // re-renders the collection view, showing the empty view
  cv.setFilter(function (child, index, collection) { return false; });

  // updates the filter, but does not re-render
  cv.setFilter(function (child, index, collection) { return true; }, { preventRender: true });

  // shows all views, using the new filter
  cv.render();

So why use setFilter instead of manually calling render? I see this as a classic case of wanting to do something whenever you change a value, which is the exact use case of a setter. It's also easily overridable in case the users don't want this behavior (and it's entirely opt-in and thus BC).

I'm also explicitly avoiding Object.defineProperty setters to maintain compatibility with IE8 and because that could result in difficult-to-customize behavior. It might not be modern semantic JS, but I think it's the best way to handle this behavior in the present.

@ianmstew
Copy link
Member

ianmstew commented Jul 1, 2015

Hey guys, any issue moving this one into 2.5 considering #2592 is targeting 2.5 already? @ahumphreys87

@ahumphreys87
Copy link
Member

yeah sounds good @ianmstew

@ahumphreys87 ahumphreys87 modified the milestones: v2.5, v3.0.0 Jul 7, 2015
@paulfalgout
Copy link
Member

Looks like this was merged by @ahumphreys87

@paulfalgout paulfalgout modified the milestone: v2.5 Aug 18, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants