bruh
bruh

Reputation: 2305

Angularjs accessing object index

I want to check the state of a property (true or false), on each object to determine weather or not to display a div.

For example, the following works great. Show "Student" heading if students.length > 0, then greet each student by name individually.

<div ng-if="ctrl.classroomInfo.students.length > 0">
  <h1>Students</h1>
  <ul>
    <li ng-repeat="student in ctrl.classroomInfo.students">
      Welcome, {{student}}!
    </li>
  </ul>
</div>

But what if I wanted to add another condition? I only want to show this classroomInfo <div> if atleast one student has good grades.

 <div ng-if="ctrl.classroomInfo.students.length > 0 &&
   ctrl.classroomInfo.students[$index].hasGoodGrades === true">
      <h1>Students</h1>
      <ul>
        <li ng-repeat="student in ctrl.classroomInfo.students">
          Welcome, {{student}}!
        </li>
      </ul>
    </div>

In the above code block I have added students[$index].hasGoodGrades === true, but $index only works in combination with ng-repeat. Meaning I would need to add:

ng-repeat="student in ctrl.classroomInfo.students" to my div tag. This is bad because it will repeat the <h1>Students</h1> header for each student with good grades.

How can I access the hasGoodGrades property on each student object to determine weather or not to show this entire div?

UPDATE:

Thanks for the answers regarding filters. How do I handle a case where the filtered property is another level deep? For example:

ctrl.classroomInfo.students.RESULTS.hasGoodGrades

ng-if="(ctrl.classroomInfo.students | filter:{RESULTS.hasGoodGrades:true}).length > 0" doesn't work

Upvotes: 1

Views: 117

Answers (4)

DIEGO CARRASCAL
DIEGO CARRASCAL

Reputation: 2129

To do the test inside the loop:

<div ng-if="ctrl.classroomInfo.students.length > 0">
   <h1>Students</h1>
      <ul>
        <li ng-repeat="student in ctrl.classroomInfo.students">
          <span ng-if="student.hasGoodGrades === true">Welcome, {{student}}!</span>
       </li>
     </ul>
</div>

but the structure for each class will be created...

Upvotes: 0

jusopi
jusopi

Reputation: 6813

You can achieve this either by creating a filter that returns a boolean OR a controller method that returns a boolean. I advocate using a filter to keep your view controllers DRY.

.filter( 'hasGoodGrades', [
    function(){
        return function( students ){
            if( students && students.length )
            {
                 var i = 0, m = students.length, student
                 for( i; i < m; i++ )
                 {
                      student = students[ i ]
                      if( student.hasGoodGrades )
                           return true
                 }
            }

            return false
        }
    }
])

Use the filter in your ng-if like this:

 <div ng-if="ctrl.classroomInfo.students | hasGoodGrades">

EDIT

I'll leave the answer here as an alternative to the other answer. Mine is a little more explicit and more readable, but I think I prefer @jstell's answer better - https://stackoverflow.com/a/39129784/1121919

Upvotes: 2

You can use a filter in your ng-if or ng-show condition, like this:

    <div ng-show="(ctrl.classroomInfo.students | filter:filter(condition)).length">

      <div ng-repeat="student in ctrl.classroomInfo.students">
        {{student.name}}
      </div>
    </div>

Upvotes: 0

jstell
jstell

Reputation: 706

Use a filter:

<div ng-if="(ctrl.classroomInfo.students | filter:{hasGoodGrades:true}).length > 0">

Upvotes: 2

Related Questions