52

I am trying to display a binary tree of elements, which I go through recursively with ng-include.

What is the difference between ng-init="item = item.left" and ng-repeat="item in item.left" ? In this example it behaves exactly the same, but I use similiar code in a project and there it behaves differently. I suppose it's because of Angular scopes. Maybe I shouldn't use ng-if, please explain me how to do it better.

The pane.html is:

<div ng-if="!isArray(item.left)">
    <div ng-repeat="item in [item.left]" ng-include="'Views/pane.html'">
    </div>
</div>
<div ng-if="isArray(item.left)">
    {{item.left[0]}}
</div>
<div ng-if="!isArray(item.right)">
    <div ng-repeat="item in [item.right]" ng-include="'Views/pane.html'">
    </div>
</div>
<div ng-if="isArray(item.right)">
    {{item.right[0]}}
</div>

<div ng-if="!isArray(item.left)">
    <div ng-init = "item = item.left" ng-include="'Views/pane.html'">
    </div>
</div>
<div ng-if="isArray(item.left)">
    {{item.left[0]}}
</div>
<div ng-if="!isArray(item.right)">
    <div ng-init="item = item.right" ng-include="'Views/pane.html'">
    </div>
</div>
<div ng-if="isArray(item.right)">
    {{item.right[0]}}
</div>

The controller is:

var app = angular.module('mycontrollers', []);

app.controller('MainCtrl', function ($scope) {

    $scope.tree = {
        left: {
            left: ["leftleft"],
            right: {
                left: ["leftrightleft"],
                right: ["leftrightright"]
            }
        },
        right: {
            left: ["rightleft"],
            right: ["rightright"]
        }
    };

    $scope.isArray = function (item) {
        return Array.isArray(item);
    }
});

EDIT: First I run into the problem that the directive ng-repeat has a greater priority than ng-if. I tried to combine them, which failed. IMO it's strange that ng-repeat dominates ng-if.

Johannes
  • 2,442
  • 4
  • 20
  • 32
  • A solution is create a new directive, as i said in this answer: http://stackoverflow.com/a/36916276/2516399 – smartmouse Apr 28 '16 at 13:35

4 Answers4

50

Pass parameter to Angular ng-include

You don't need that. all ng-include's sources have the same controller. So each view sees the same data.

What is the difference between ng-init="item = item.left" and ng-repeat="item in item.left"

[1]

ng-init="item = item.left" means - creating new instance named item that equals to item.left. In other words you achieve the same by writing in controller:

$scope.item = $scope.item.left

[2]

ng-repeat="item in item.left" means create list of scopes based on item.left array. You should know that each item in ng-repeat has its private scope


I am trying to display a binary tree of elements, which I go through recursively with ng-include.

I posted in the past answer how to display tree by using ng-include.

It might helpful: how-do-display-a-collapsible-tree

The main part here that you create Node with id wrapped by <scipt> tag and use ng-repeat:

  <script type="text/ng-template"  id="tree_item_renderer">
        <ul class="some" ng-show="data.show"> 
          <li ng-repeat="data in data.nodes" class="parent_li"  ng-include="'tree_item_renderer'" tree-node></li>
        </ul>
  </script>


<ul>
  <li ng-repeat="data in displayTree"  ng-include="'tree_item_renderer'"></li>

Community
  • 1
  • 1
Maxim Shoustin
  • 76,444
  • 28
  • 192
  • 219
  • Thank you for your answer. It was really helpful. I'll try to write a directive, similiar to your diretives `'node'` and `'nodeTree'` – Johannes Aug 29 '14 at 12:23
48

It's a little hacky, but I am passing variables to an ng-include with an ng-repeat of an array containing a JSON object :

<div ng-repeat="pass in [{'text':'hello'}]" ng-include="'includepage.html'"></div>

In your include page you can access your variable like this:

<p>{{pass.text}}</p>
Kars Barendrecht
  • 463
  • 8
  • 21
Junus Ergin
  • 481
  • 4
  • 2
  • 8
    Definitely hacky, but I'm totally using it! – Software Prophets Jul 29 '16 at 19:36
  • #MEGA. Not perfect for long term, but as I'm going through a huge refactor this is coming in handy – Jamadan May 17 '17 at 09:14
  • What dark magic is this?! It's so simple that I cant believe I haven't thought of this before. I need to display multiple contacts off of a single object, and the contact view has been extracted to template html, but passing in each contact without hard coding it was eluding me. Thanks for this! – Stephan Jan 29 '18 at 15:23
  • @Jamadan, what options are better for a long term from you pov? :) – hellouworld Mar 18 '20 at 09:42
  • @hellouworld - lol, I don't even remember what project I was working on here. Haven't written Angular since this I think! I have a vague memory of updating some of the data structures coming back from my API so that I didn't need to do this. Sorry can't be of more help. – Jamadan Mar 21 '20 at 22:15
5

Making a generic directive instead of ng-include is a cleaner solution: Angular passing scope to ng-include

dvdmn
  • 5,659
  • 6
  • 39
  • 51
665
  • 175
  • 2
  • 2
3

I am using ng-include with ng-repeat of an array containing string. If you want to send multple data so please see Junus Ergin answer.

See my code Snippet:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="">
<div ng-repeat="name in ['Sanjib Pradhan']" ng-include="'your_template.html'"></div>
<div ng-repeat="name in ['Chinmay Sahu']" ng-include="'your_template.html'"></div>


    <script type="text/ng-template" id="your_template.html">
          {{name}}
    </script>
  </div>
Community
  • 1
  • 1
Chinmay235
  • 3,456
  • 8
  • 49
  • 81