3

For a autocomplete input I search in project properties during typing. Now I want to improve this code

filterProjects(value: string) {
  return this.projects.filter(
    project =>
      project.key.toLowerCase().indexOf(value.toLowerCase().trim()) >=
        0 ||
      project.name.toLowerCase().indexOf(value.toLowerCase().trim()) >=
        0 ||
      project.description?.toLowerCase().indexOf(value.toLowerCase().trim()) >=
        0
  );
}

with this:

filterProjects(value: string) {
  return this.projects.filter(project =>
    [project.key, project.name, project.description].map(
      str => str?.toLowerCase().indexOf(value.toLowerCase().trim()) >= 0
    )
  );
}

I use the optional chaining because description can be null or undefined.

But it doesn't work, meaning the function always returns the array unmodified. Also, when the value is found in the description of one item, the array doesn't get filtered to only this item.

What could be the solution except using "old" checks like if (str !== undefined) and such?

Jean D.
  • 169
  • 3
  • 15

2 Answers2

4

That map returns an array of booleans, which is always truthy no matter what, so it's not the predicate you are looking for. You need Array.some (also in lodash/underscore/ramda, if you plan to target old browsers). Let me tweak also the inner predicate a little bit:

filterProjects(value: string) {
  return this.projects.filter(project =>
    [project.key, project.name, project.description].some(str =>
      str ? str.toLowerCase().includes(value.toLowerCase().trim()) : false
    )
  );
}
tokland
  • 66,169
  • 13
  • 144
  • 170
  • Neat, works! But I'm still thinking of a way to get rid of the ternary operator ... – Jean D. Jun 20 '20 at 15:24
  • 1
    What @sivako proposes - `(str ?? "")` or `(str || "") - is also a valid and quite typical approach. – tokland Jun 20 '20 at 20:54
  • 1
    @JeanD, With this Nice fix of using `some`, you can try with optional chaining `(str) => str?.toLowerCase().indexOf(value?.toLowerCase().trim()) >= 0` (or `str => (str ?? "").toLowerCase().indexOf((value ?? "").toLowerCase().trim()) >= 0` – Siva K V Jun 22 '20 at 16:59
  • @sivako Great, this works perfect now and is my preferred solution: `str => str?.toLowerCase().indexOf(value?.toLowerCase().trim()) >= 0` – Jean D. Jun 23 '20 at 06:50
2

You can use `Nullish coalescing operator (??)'

like

str => (str ?? "").toLowerCase().indexOf(value.toLowerCase().trim()) >= 0
Siva K V
  • 10,561
  • 2
  • 16
  • 29