Handle two or more properties in just one computed property

My code is here:

https://ember-twiddle.com/b894cec64a1d78a71e15b642d512cfcf

I need to use this computed property: “postsFiltered” with both Category and Search but when I change category on clickCategory() I need to reset the search text (if present).

But then the computed property is already called? No?

And the same when I search something I need to reset category to null.

postsFiltered: Ember.computed('category', 'search', function () {

var posts = this.get('posts');
var search = this.get('search');

console.log('computed postsFiltered() with category: ' + this.get('category') + ', search: ' + search);
return posts.filter((item) => item['categoryId'] === this.get('category'));

// or this when I search, but I don't know how to do one or the other:
// return posts.filter((item) => item['name'].includes(search));
}),

How to handle two properties in the same computed property?

searchPosts: Ember.computed('posts.@each.name', 'search', function() {
  var posts = this.get('posts');
  var search = this.get('search');
  return posts.filter(post => post.name.includes(search));
}),

categoryPosts: Ember.computed.filterBy('posts', 'categoryId', 'category'),

displayPosts: Ember.computed('searchPosts', 'categoryPosts', 'search', function() {
  if (this.get('search') {
    return this.get('searchPosts');
  } else {
    return this.get('categoryPosts');
  }
}),

Thanks @onsmith, I had already thought of something like that, with still a lot of confusion.

But another person recommended me this:

You need to introduce search:'', in controller, and pass it down to posts component {{my-posts posts=posts category=category search=search}} and your clickCategory should reset search property when category clicked

clickCategory(categoryId) {
   this.set('category', categoryId);
   this.set('search','');
}

This will ensure that you are following Data Down Actions Up strategy. twiddle

What do you think about it?

categoryPosts: Ember.computed.filterBy(‘posts’, ‘categoryId’, ‘category’)

Ember.computed.filterBy here the last argument is expecting value, it looks you are passing property name. and also we need to recompute this categoryPosts for category property change too, so below code solves categoryPosts is not recalculating issue.

categoryPosts: Ember.computed(‘posts.’,‘category’, function(){ return this.get(‘posts’).filter(post => post.categoryId === this.get(‘category’)); }),

1 Like

@kumkanillam is right. Updated version below:

searchPosts: Ember.computed('posts.@each.name', 'search', function() {
  const posts  = this.get('posts');
  const search = this.get('search');
  return posts.filter(post => post.name.includes(search));
}),

categoryPosts: Ember.computed('posts.@each.categoryId', 'category', function() {
  const posts    = this.get('posts');
  const category = this.get('category');
  return posts.filter(post => post.categoryId === category);
}),

displayPosts: Ember.computed('searchPosts', 'categoryPosts', 'search', function() {
  if (this.get('search') {
    return this.get('searchPosts');
  } else {
    return this.get('categoryPosts');
  }
}),

@johnunclesam, the recommendation is a good idea if you want the search term to disappear whenever a category is selected. It depends on the behavior you’re looking for in your app.

Maybe you want both category and search to filter posts at the same time. That would require you to tweak the code a bit.

1 Like