2

I have an ng-repeat that iterates over an array of objects. Each object has a type property and a contents array. Inside the ng-repeat, I would like to display the contents array different depending on the type of the object, so I am conditionally displaying content with an ng-if.

The problem is it appears the ng-repeat is executing and rendering regardless of if the ng-if is truthy or falsey, and that when ng-if is falsey that it's not removing the ng-repeat DOM elements.

I'm not sure if there's something wrong with the implementation, or if these angular directives aren't meant to be used quite like this - or if there's a better way to solve this problem in angular.

Below are the snippets, and here is a working plunker: http://plnkr.co/edit/FZQ5CM8UFOepNIHHuTD4?p=preview

The HTML:

<div ng-controller="FunkyCtrl as vm">
  <div ng-repeat="thing in vm.twoThings">

    <p ng-if="thing.type === 'apple'">
      <span>Type: {{thing.type}}</span>
      <ul>
        <li ng-repeat="content in thing.contents">Food: {{content.stuff}}</li>
      </ul>
    </p>

    <p ng-if="thing.type === 'dog'">
      <span>Type: {{thing.type}}</span>
      <ul>
        <li ng-repeat="content in thing.contents">Guts: {{content.stuff}}</li>
      </ul>
    </p>

  </div>
</div>

The script:

(function(angular) {
  angular.module('funkyStuff', []);
  angular.module('funkyStuff').controller('FunkyCtrl', FunkyCtrl);

  function FunkyCtrl() {
    var vm = this;
    vm.twoThings = [
      {
        type: 'apple',
        contents: [
          {
            stuff: 'apple slices'
          },
          {
            stuff: 'juice'
          }
        ],
      },
      {
        type: 'dog',
        contents: [
          {
            stuff: 'bones'
          },
          {
            stuff: 'meat'
          }
        ]
      }
    ];
  }
})(angular);

Expected Output:

Type: apple

  • Food: apple slices
  • Food: juice

Type: dog

  • Guts: bones
  • Guts: meat

Actual Output:

Type: apple

  • Food: apple slices
  • Food: juice

  • Guts: apple slices

  • Guts: juice

  • Food: bones

  • Food: meat

Type: dog

  • Guts: bones
  • Guts: meat
anjunatl
  • 1,027
  • 2
  • 11
  • 24

1 Answers1

6

It's because your HTML is invalid. The ul element is not allowed inside p.

If you inspect the rendered HTML you will notice that the ul has been rendered outside the p (might depend on the browser implementation of course).

Replace p with for example div and you will get the result you expect.

Demo: http://plnkr.co/edit/pBVZ4jIJ5qzRsa8xZbud?p=preview

If you want to know which elements are allowed inside p you can find a good answer here.

Community
  • 1
  • 1
tasseKATT
  • 38,470
  • 8
  • 84
  • 65