Filtering a list of Observables with complex objects

Hi, guys!

I have a doubt regarding filtering a list of Observables which has a complex object. So, considering this example:

var searchString = Observable("");

fruits = Observable(
    { name: "Apple" , color: "red"    },
    { name: "Lemon" , color: "yellow" });

    var filteredList = searchString.flatMap(function(searchTerm) {
      return fruits.where(function(fruit) {
        return stringContainsValue(fruit.name, searchTerm);
      });
    });

    function stringContainsValue(main, filter){
      return main.toLowerCase().trim().indexOf(filter.toLowerCase().trim()) != -1;
    }

This works ok in scenarios where I have a ux file like this:

        <Each Items="{filteredList}">
          <FruitsList />
        </Each>
        ...

But, when considering this scenario:

fruits = Observable(
    { name: "Apple" , color: "red", categories: [{category: "category 1", type: "type 1"}, {category: "category 2", type: "type 2"}]  },
    { name: "Lemon" , color: "yellow", categories: [{category: "category 3", type: "type 3"}, {category: "category 4", type: "type 4"}] });

And, in the ux file:


        <Each Items="{filteredList}">
          <FruitsList />
        </Each>
        ...

        <Panel ux:Class="FruitsList">
           <Panel ux:Name="header">
              <Text Value="{name}" />
           </Panel>
           <Each Items="{categories}">
             <Text Value="{category}" />
             <Text Value="{type}" />
           </Each>
        </Panel>    

How can I adapt the filteredList function to work in this case, when I have a nested “Each”? I tried something like this with no success:

    var filteredList = searchString.flatMap(function(searchTerm) {
      return fruits.where(function(fruit) {
        return fruit.where(function(cat) {
          return stringContainsValue(cat.categories.name, searchTerm);
        });
      });
    });

I need a list with a header and, for each headers, a list of categories which I’m allowed to filter based on a condition.

Thanks in advance!

Hi Carlos,

here’s a way to filter the list of fruits by searching for matches in category names only:

var filteredList = searchString.flatMap(function(searchTerm) {
  return fruits.where(function(fruit) {
    // if the searchTerm is empty, all fruits must match anyway
    if (searchTerm == "") {
        return true;
    } else {
        // otherwise, we need to loop through categories and check for at least one match
        var match = false;
        fruit.categories.forEach(function(cat) {
            if (stringContainsValue(cat.category, searchTerm)) {
                match = true;
            }
        });
        return match;
    }
  });
});

Note that you can not use .where() operator on something that is not an Observable. So in your last snippet where you have this:

return fruit.where(function(cat) {

it simply won’t work, because the fruit itself is not an Observable.

Awesome! It worked like a charm! Based on your code, I even end up understanding more about how the “where” function properly works.

Thank you, Uldis.