0

I've done filtering numerous times before, but am having trouble with this specific case. I have a list of objects set up in pagination, but I also want to be able to filter them for ease of use. An example object might look like:

{
    baseline:0.75
    clonedFrom:Object
    description:"Just a simple description.."
    includeable:false
    key:"bc889881-7979-4e04-b586-d53faab26b6b"
    name:"Just a simple question?"
    type:"BayesianModel"
    version:1483477351992
    versionComment:null
    versionLabel:"0.11"
}

For the most part, what the object looks like is arbitrary, I just included it for ease of answering. I am trying to filter on both the name and description of the object at the same time. For example if the user knew a key word in either they could narrow down the results.

I have the input for the filter and the results inside of a <ul> shown below:

<ul class="list-group">
  <li class="list-group-item">
    <div class="form-group has-feedback">
      <input type="text"
          ng-model="vm.resultFilter"
          ng-change="vm.updateFilter()"
          class="form-control filterInput"
          placeholder="Filter Results" />
      <span ng-if="vm.resultFilter"
          ng-click="vm.resultFilter = ''; vm.updateFilter();"
          class="fa fa-times fa-lg form-control-feedback">
      </span>
    </div>
  </li>
  <li class="list-group-item link-row model-list"
      ng-repeat="result in vm.filteredResults
          | startFrom : ((vm.currentPage - 1) * vm.itemsPerPage)
          | limitTo: vm.itemsPerPage"
      ng-if="result.name != vm.model.name"
      ng-click="vm.selected = result;"
      ng-class="{selected: result === vm.selected}"
      ng-init="displayNumber = vm.incrementDisplayIndex();">
    <h4 class="list-group-item-heading">{{result.description}} - {{result.name !== vm.model.name}}</h4>
    <p class="list-group-item-text">
      {{result.name}}
    </p>
  </li>
</ul>

So the name of the filter is vm.resultFilter and the cooresponding method that is called every time the filter is updated is updateFilter() (which is necessary for the pagination stuff).

function updateFilter() {
  vm.filteredResults = $filter('filter')(vm.results, {
    'name': vm.resultFilter,
    'description': vm.resultFilter
  });
  vm.totalItems = vm.filteredResults.length;
  vm.noOfPages = Math.ceil(vm.filteredResults.length / vm.itemsPerPage);
}

I am just having trouble with getting the filtering to work 100%. Sometimes it appears it's only filtering on the description field, but then sometimes I will search a word that is in the description field of only one result and it will filter with no results (which would be false). Any tips appreciated.

4
  • Take into account that your filter works with and AND operator. It means, that a result must match both conditions name and description to be a result. Commented Jan 9, 2017 at 13:08
  • I understand what you mean, but I am not using an AND operator anywhere? Unless, by pointing both fields to vm.resultFilter that is what is happening. If that is the case, how then do I make that an OR operator? Commented Jan 9, 2017 at 13:13
  • Pointing both fields, makes the filter to work under the AND condition. This might be helpful stackoverflow.com/questions/15868248/… Commented Jan 9, 2017 at 13:22
  • I appreciate the link. I had already looked @ that, and the result of that problem is only filtering on one field of the object. It's just whether or not it equals family or action which both reside under the genre field of the object. I am trying to OR two different fields I guess. Commented Jan 9, 2017 at 13:31

1 Answer 1

1

Since your are not using the filter inside your HTML, I recommend you to use the filter property from the Array prototype.

function updateFilter() {
  vm.filteredResults = vm.results.filter(function(item){
    return (item.name==vm.resultFilter || item.description==vm.resultFilter )
  }

  vm.totalItems = vm.filteredResults.length;
  vm.noOfPages = Math.ceil(vm.filteredResults.length / vm.itemsPerPage);
}

In case you need to determines whether a string contains the characters of a specified string. You might need to use includes instead of ==

vm.filteredResults = vm.results.filter(function(item){
   return (item.name.includes(vm.resultFilter) || item.description.includes(vm.resultFilter) )
}
Sign up to request clarification or add additional context in comments.

4 Comments

Great. So the second one is more of what I am looking for. Just a curious question if you know off the top of your head: Do you know how to make the filtering in this case non case sensitive? Angular by default is, though in this case since it is 'does it include the string' obviously it's going to be case sensitive (which for me is undesirable)
transform both string to lower-case with the String property .toLowerCase() item.name.toLowerCase().includes(vm.resultFilter.toLowerCase())
okay cool, yea that was the obvious solution ;) but just seeing if I had other options. thanks for the help today m8
anytime, as far as I know, you do not have an option to set that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.