简体   繁体   中英

Add controls to ng-repeat to filter data

I have some json data that I output with ng-repeat and I have added some form controls to filter data output from another json.

Simplified sample

First JSON data:

var technologies = [
  {"id":"5", "slug":"mysql", "label":"MySQL", "category":"database"},
  {"id":"4", "slug":"html", "label":"HTML", "category":"markup"}
]

and the output:

<ul>
  <li ng-repeat="tech in technologies">
    <span>{{tech.label}}</span> 
    <span><label>required expertise 
      <select>
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
      </select></label>
    </span>
  </li>
</ul>

(actually, the technologies are at this point already filtered from another choice that the user makes on a different page, but I assume that makes no difference)

The 2nd json contains the expertise property that I want to use as a filter

var people = [
{
  'label': 'MySQL',
  'slug': 'mysql',
  'talents':[
    {
      'name': 'Stanislav Lem',
      'expertise': 5,
      'desire': 0,
      'last_used': '2009-01'
    },
    {
      'name': 'Ijon Tichy',
      'expertise': 1,
      'desire': 5,
      'last_used': '2011-06'
    }
  ]
},  ...
]

...and that is for now being plain used as

<ul>
  <li ng-repeat="item in people">
    {{item.label}}<br>
    <ul>
      <li ng-repeat="person in item.talents">{{person.name}} &middot; Expertise: {{person.expertise}}</li>
    </ul>
  </li>
</ul>

What I need is a filter that uses the options from the first output to filter the second output. For example when MySQL required expertise is set to '2', only Stanislav Lem will be displayed. Actually I will also need a 'no results found' message if the noone matches the expertise, but I guess I can figure that part out myself.

Plunker sample is here: http://plnkr.co/edit/B0aQp9aCJ2g4OM6fZ3qe?p=preview

Working Plunker: http://plnkr.co/edit/jcb6SfKVPkwt7FFCZFHX?p=preview

The first thing you'll need to do is add an ng-model attribute to the select . I've added this as a property of the technology so you can easily find it.

<select ng-model="tech.required">

Next, I added the following two functions to your controller to aid in filtering the second list:

$scope.getFilterForSlug = function(slug) {
    var technology = getTechBySlug(slug);

    return function(person) {
        return person.expertise >= (technology.required || 0);
    }
}

function getTechBySlug(slug) {
    return _.find($scope.technologies, {
        slug: slug
    });
}

I'm using lodash in getTechBySlug , as the name states, to get the correct technology object based on the slug. Using that, getFilterForSlug returns a function which compares the person's expertise level with the desired level from the select . If an option wasn't selected, then the desired level is set to 0.

Lastly, in the HTML, I added the following:

<ul>
    <li ng-repeat="person in filteredPeople = (item.talents | filter: getFilterForSlug(item.slug))">{{person.name}} · Expertise: {{person.expertise}}</li>
</ul>
<span ng-if='!filteredPeople.length'>No Results!</span>

This code gets a filter based on the current slug, and then filters the people using that function. It stores the results in a variable filteredPeople , which is used in the span to display a message when there are no results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM