keeping track of nested ng-repeat index's - javascript

So I have a nested ng-repeat like so:
<div ng-repeat="data in flow" ng-init="$flowIndex = $index">
Index: {{ $index }}
<div ng-click="flow.splice($index, 1)">Delete me</div>
<div ng-repeat="inside_data in flow[$flowIndex]">
Inside index: {{ $index }}
</div>
</div>
I want to be able to delete index in my $flowIndex. However if I have something like this:
0
1
2
3
And I delete index 2. If I go and delete index 3, it isn't found because ng-init variable still things its at index 3 but really its not at index 2.
Does anyone know a work around?

You can get rid of $flowIndex, it's not necessary, you can use $parent.$index instead, when you are using ngRepeat it creates a child scope and $index is part of that scope. Also consider moving your deleting logic into the controller.
Controller:
$scope.delete = function ($index) {
$scope.flow.splice($index, 1);
};
Html:
<div ng-repeat="data in flow">
Index: {{ $index }}
<div ng-click="delete($index)">Delete me</div>
<div ng-repeat="inside_data in flow[$index]">
Inside index: {{ $parent.$index }} -> {{ $index }}
</div>
</div>

I believe you can get the parent index like so:
$parent.$index
As mentioned in this answer: passing 2 $index values within nested ng-repeat
That way you don't have to worry about your variable being out of sync with your current state.

I just tested your similar code with some dummy data strings and the delete appears to work. I made some updates to your code to better analyze it.
// Code goes here
var myApp = angular.module('myApp',[]);
myApp.controller('MyController', ['$scope', function($scope) {
$scope.flow = [
["test01","test02","test03"],
["test11","test12","test13"],
["test21","test22","test23"],
["test31","test32","test33"],
["test41","test42","test43"]
]
;
}]);
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.5.8" data-semver="1.5.8" src="//opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<section ng-controller="MyController">
<div ng-repeat="data in flow">
Index: {{ $index }}
<div ng-click="flow.splice($index, 1)">Delete me [{{ $index }}]</div>
<div ng-repeat="inside_data in flow[$index]">
Inside index: {{ $index }} : {{ inside_data }}
</div>
<hr>
</div>
</section>
</body>
</html>

Related

Mixing 2 json to in 1 . How ? ( AngularJS )

Get 2 json files from backend , and need to mix it !
First ng-repeat:
<p ng-repeat="category in categories track by category.id" >
{{ category }}
</p>
result
{"id":"Category-1"}
{"id":"Category-2"}
{"id":"Category-3"}
Second ng-repeat:
<p ng-repeat="game in gamesList track by game.id">
{{ game }}
</p>
result
{"Category-id":"1","title":"Game-1"}
{"Category-id":"1","title":"Game-2"}
{"Category-id":"2","title":"Game-3"}
{"Category-id":"3","title":"Game-4"}
{"Category-id":"3","title":"Game-5"}
I need to mix this 2 values and get something like this:
Category-1
Game-1
Game-2
Category-2
Game-3
Category-3
Game-4
Game-5
You do not have to mix both json, you can just use the 2nd json and use GroupBy Filter
DEMO
angular.module('datepickerBasicUsage', ['angular.filter'])
.controller('AppCtrl', function ($scope) {
$scope.gamesList = [{"Categoryid":"1","title":"Game-1"},
{"Categoryid":"1","title":"Game-2"},
{"Categoryid":"2","title":"Game-3"},
{"Categoryid":"3","title":"Game-4"},
{"Categoryid":"3","title":"Game-5"}];
});
<!doctype html>
<html ng-app="datepickerBasicUsage">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.8/angular-filter.js"></script>
</head>
<body>
<div ng-controller="AppCtrl" style='padding: 40px;'>
<ul ng-repeat="(key, value) in gamesList | groupBy: 'Categoryid'">
<h3> Category: {{ key }} </h3>
<li ng-repeat="player in value">
{{ player.title }}
</li>
</ul>
</div>
</body>
</html>

Add JavaScript logic in dynamically loaded template AngularJS

I'm dynamically loading templates which is working fine. Now my concern is I need to add a JavaScript logic to template
I need to use something like this in my template.
{{ var entries = 0; }}
{{ for(var r = 0; r < d; r++) }}
Suppose my template returns this HTML
<div ng-repeat="x in names" ><span>{{x.name}}</span>{{some logic here which is plain js. var a=[] if(a=b){}}}</div>
My question is how to achieve this.
<div ng-repeat="entry in entries track by $index">
{{entry}},{{$index}}
</div>
Use ng-repeat.
<div ng-repeat="entry in entries">
{{entry}}
</div>
If you need the index:
<div ng-repeat="entry in entries">
{{entry}},{{$index}}
</div>
Docs: https://docs.angularjs.org/api/ng/directive/ngRepeat
<div ng-init="entries[0,1,2,3,4]">//Use ng-int to initialize data
<div ng-repeat="data in entries">// use ng-repeat to loop over
{{data}}
</div>
</div>

AngularJS pass variable through to a template

I want to pass a variable or text through to a template so that it shows the value inside my template.
I come across jsFiddle which shows it working but it uses ng-repeat. Is there a simplere way to do this without using ng-repeat?
<div ng-repeat="name in ['John']" ng-include="'partial.html'"></div>
<div ng-repeat="name in ['Jack']" ng-include="'partial.html'"></div>
<script type="text/ng-template" id="partial.html">
<div>The name is {{ name }}</div>
</script>
http://jsfiddle.net/f97keutL/
<div ng-controller="ctrl">
<div ng-include="'partial.html'"></div>
</div>
<script type="text/ng-template" id="partial.html">
<div>The name is {{ name }}</div>
</script>
JS:
var myApp = angular.module('myApp',[]);
myApp.controller('ctrl', function($scope) {
$scope.name = "John";
});
You just set the variable in the scope, and include the template?

Pass parameter to Angular ng-include

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.
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>
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>
Making a generic directive instead of ng-include is a cleaner solution:
Angular passing scope to ng-include
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>

How can I give each ng-model in an ng-repeat a unique identifier?

I have a page with multiple AngularUI sliders, and a span displaying the value of each slider with an ng-bind. It looks something like this:
<div class="formitem" ng-repeat="food in foodlist" >
<div ui-slider="{range: 'min'}" min="0" max="{{ unit.max }}" ng-model="demoVals.slider" class="food-slider" >
<div class="begin">1</div>
<div class="end"> {{ unit.max }} {{ food.uid }} </div>
</div>
<span ng-bind="demoVals.slider"></span>
</div>
I want the ng-model to be unique for each food item, so something like demoVals.slider57, where 57 is the output of {{ food.uid }}. I can get {{ food.uid }} to print out in the template just fine, but if I try to add it to the ng-model or ng-bind, I just get this:
ng-model="demoVals.slider[food.uid]"
How can I add the food.uid to the ng-model of each food item?
It does not seem to be a good architectural choice to use individual elements instead of using an array. You should really try to switch to put your slider values into an array.
However, you can use some controller function to achieve what you want, although it is rather ugly. Within your ng-repeat you can bind to a function
<div ng-bind="test(food.uid)"></div>
with the function being
$scope.test = function test(v) {
var t = $scope.$eval("demoVals.slider" + v);
return t;
};
You want to add a food.uid property to demoVals for each iteration. This brings the need to execute js code on each iteration. That can be only be done (IMHO)in a directive.
So here is a working plunker
Here is how you should modify your html ( notice the repeat-directive ... directive :)
<div class="formitem" ng-repeat="food in foodlist" repeat-directive>
<div ui-slider="{range: 'min'}" min="0" max="{{ unit.max }}" ng-model="demoVals.slider" class="food-slider" >
<div class="begin">1</div>
<div class="end"> {{ unit.max }} {{ food.uid }} </div>
</div>
<span ng-bind="demoVals.slider"></span>
here is the code for the direective that will be executed on every iteration:
var app = angular.module('plunker', [])
.directive ('repeatDirective',function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
console.log('linking directive ',scope.demoVals)
if (scope.food){
// you have a value for food
// you can add it as an attribute to demoVals
scope.demoVals['prop'+scope.food.uid] = scope.food.name;
}}
}
});

Categories

Resources