Handle nested ng-repeat in AngularJS - angularjs

I am newbie in Angular js. Trying to use ng-repeat in following way
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.names = ["Emil", "Tobias", "rajeev", "sandeep","deepak"];
});
<div class="dynamicTile" ng-app="myApp" ng-controller="myCtrl">
<div class="row">
<div class="col-sm-6 col-xs-6">
<div id="{{ 'tile' + $index }}" class="tile" ng-repeat="x in names">
<h1>myNewTile</h1>
</div>
</div>
</div>
</div>
It gives me structure like this
myNewTile
myNewTile
myNewTile
myNewTile
myNewTile
I wanna every row contain only two tiles. For third and fourth tile new row should be created and so on. something like this
myNewTile myNewTile
myNewTile myNewTile
myNewTile

You have two options:
First Solution
Just put the ng-repeat in your column div:
<div class="dynamicTile" ng-app="myApp" ng-controller="myCtrl">
<div class="row">
<div class="col-sm-6 col-xs-6" ng-repeat="x in names">
<div id="{{ 'tile' + $index }}" class="tile">
<h1>myNewTile</h1>
</div>
</div>
</div>
</div>
Bootstrap will take care of the rest.
OR Second Solution
The problem with the first solution will arise when the height of each columns are not same due to the content then the Bootstrap will not be able to perform proper alignment of the columns. So you can either use this one.
You can first collate your list and the put two ng-repeat inside there:
// An helper function to collate the list
Array.prototype.collate = function(size) {
var list = [];
angular.forEach(this, function(item, i) {
if (i % size === 0) {
list[Math.floor(i / size)] = [item];
} else {
list[Math.floor(i / size)].push(item);
}
});
return list;
};
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var names = ["Emil", "Tobias", "rajeev", "sandeep", "deepak"];
$scope.collatedNames = names.collate(2);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<div class="dynamicTile" ng-app="myApp" ng-controller="myCtrl">
<div class="row" ng-repeat="names in collatedNames">
<div class="col-xs-6" ng-repeat="x in names">
<div id="{{ 'tile' + $index }}" class="tile">
<h1>myNewTile</h1>
</div>
</div>
</div>
</div>

Related

angularjs ng-repeat on different arrays depending on condition

I have two arrays. If ctrl.type == 'group' I want to do an ng-repeat
<div ng-repeat="category in ctrl.categories">
...
<div ng-repeat="item in category.group_items">...</div>
</div>
else, it should be
<div ng-repeat="category in ctrl.categories">
...
<div ng-repeat="item in category.data.other_items">...</div>
</div>
what's the best way to write this? I don't want to rewrite the ... as it's the same code.
Make a function that returns the array in your controller.
ctrl.getArray = () => {
if(ctrl.type === 'something') {
return ctrl.data.group_items;
}
return ctrl.data.other_items;
}
And in the view:
<div ng-repeat="item in ctrl.getArray()">...</div>
It can also be done using ng-switch. Below is my controller code where i have defined two arrays and also defined type on which your data will be shown.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.type = 'something';
$scope.categories=[{ID:'1',Name:'Test 1'},{ID:'2',Name:'Test 2'},{ID:'3',Name:'Test 3'}];
$scope.group_items=[{ID:'1',Name:'Group 1'},{ID:'2',Name:'Group 2'},{ID:'3',Name:'Group 3'}];
});
Below is the html bindings.
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-switch="type">
<div ng-switch-when="group">
<div ng-repeat="item in categories">
<p>{{item.Name}}</p>
</div>
</div>
<div ng-switch-when="something">
<div ng-repeat="item in group_items">
<p>{{item.Name}}</p>
</div>
</div>
</div>
</div>

How can I show my json keys in an ng-repeat?

I have an array with 3 elements. Each element has a different key. How can I do to show only the name of the keys?
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-repeat="item in names">
{{item}}
</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.names=
[
{"joe":1},
{"pablo":2},
{"greic":3}
]
//output should be:
//joe
//pablo
//greic
});
http://jsfiddle.net/8wq4qmh0/
You can pull out key and values with (x,y) syntax. But since it's an array of objects, you need another ng-repeat.
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.names = [{"joe": 1},{"pablo": 2},{"greic": 3}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-repeat="item in names"> <!-- pull object from the array -->
<div ng-repeat="(key, val) in item"> <!-- pull key and value from the object -->
{{key}}
</div>
</div>
</div>
</div>

ng-repeat with i class

<div class="col-md-4 col-sm-6 col-xs-12 featured" ng-repeat="item in beds">
<div class="stars" ng-repeat="t in [item.Value.Rate]">
<i class="fa fa-star"></i>
</div>
</div>
This is my code. when i want to use ng-repeat second time, it's not working. i want something like that:
if [item.Value.Rate] return 3, append <i class="fa fa-star"></i> 3 times, if it returns 1, just one <i class="fa fa-star"></i>
Here is a directive definition which I think solves the problem you had in your mind, If you are new to angular I suggest you to first check the directive docs
Edit:
Use lodash to generate range and use that array in ng-repeat.
var app = angular.module('app', []);
app.directive('starRating', function () {
return {
scope: {
value: '='
},
template: '<div class="stars"><i class="fa fa-star" ng-repeat="r in entries"></i></div>',
controller: function ($scope) {
$scope.entries = _.range($scope.value);
}
}
});
app.controller('Ctrl', function($scope) {
var ctrl = this;
ctrl.beds = [
{
Value: {
Rate: 5
}
},
{
Value: {
Rate: 2
}
},
{
Value: {
Rate: 3
}
}
];
return ctrl;
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.9" data-semver="1.4.9" src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
</head>
<body>
<div ng-controller="Ctrl as ctrl">
<div class="col-md-4 col-sm-6 col-xs-12 featured" ng-repeat="item in ctrl.beds">
<star-rating value="item.Value.Rate">
</star-rating>
</div>
</div>
</body>
</html>
ng-repeat repeats based on the number of elements. I guess here item.Value.Rate is an integer. So its not a collection and hence the repeat doesn't work.
What you can do:
in the second div use
<div class="stars" ng-repeat="t in getCustomRepeatArray(item.Value.Rate)">
and in your angular code have this:
$scope.getCustomRepeatArray(numberValue)
{
return new Array(numberValue);
}
Don't forget to upvote if you find this helpful!!
You can try this -
In your controller -
$scope.getLength = function(num) {
return new Array(num);
}
And your html -
<div class="col-md-4 col-sm-6 col-xs-12 featured" ng-repeat="item in beds">
<div class="stars" ng-repeat="t in getLength(item.Value.Rate)">
<i class="fa fa-star"></i>
</div>
</div>
https://jsfiddle.net/5u5zakub/7/
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="item in beds">
<div ng-repeat="t in getArray(item)">
<i>{{t}}</i>
</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.beds = ["1", "2"];
$scope.getArray = function(num) {
if (num == "1")
return ["a","b"];
else
return ["c","d"];
}
});

Iterate elements using ng-repeat in two diff structure

i have a code in which i want to iterate element inside two differnet row.
Is it Possible to do it using single ng-repeat because i need the above row column structure to be fixed.only content should be dynamic ?
<div class="row sortable">
<div class="col-md-6">
<div class="row">
<div class="col-md-12" ng-repeat="graph in graphs" ng-if="$even">
<div> content.....</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-12" ng-repeat="graph in graphs" ng-if="$odd">
<div> content.....</div>
</div>
</div>
</div>
</div>
Just set the ng-repeat as a parent of your rows as follow:
<div class="row sortable">
<div class="col-md-6">
<div class="col-md-12" ng-repeat="graph in graphs">
<div class="row" ng-if="$even">
<div> content.....</div>
</div>
<div class="row" ng-if="$odd">
<div> content.....</div>
</div>
</div>
</div>
</div>
UPDATE
If you don't want to repeat the <div class="row>, you can create an HTML template and use two ng-include with different controllers on the HTML parent. I created a Plunker example:
Parent HTML:
<body ng-app="includeExample">
<div ng-controller="ExampleController">
<div ng-controller="TemplateController1">
<div ng-include="template"></div>
</div>
<div ng-controller="TemplateController2">
<div ng-include="template"></div>
</div>
</div>
</body>
JS File:
(function(angular) {
'use strict';
angular.module('includeExample', ['ngAnimate'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.template = "template1.html";
}])
.controller('TemplateController1', ['$scope', function($scope) {
$scope.foo = "bar";
}])
.controller('TemplateController2', ['$scope', function($scope) {
$scope.foo = "test";
}]);
})(window.angular);
Template:
{{foo}}

Unable to get ng-switch working

I'm new to angular and i'm trying to use ng-switch to dynamically load templates using include in bootstrap modal but click doesn't seem to work. What am i doing wrong here ?
HTML
ModalContent.html
<div ng-controller="Nav" class="modal-body">
<div class="left-nav" ng-include="'LeftNav.html'"></div>
<div class="right-nav" ng-include="'RightNav.html'"></div>
</div>
LeftNav.html
<ul>
<li ng-repeat="item in items">
{{ item }}
</li>
</ul>
RightNav.html
<div ng-switch on="page">
<div ng-switch-when="Item1">
<div ng-include="'Item1.html'"></div>
</div>
<div ng-switch-when="item2">
<div ng-include="'Item2.html'"></div>
</div>
<div ng-switch-when="item3">
<div ng-include="'Item3.html'"></div>
</div>
<div ng-switch-default>
<h1>Default</h1>
</div>
</div>
JS
var app = angular.module('plunker', ['ngRoute', 'ui.bootstrap']);
app.controller('Nav', function($scope) {
$scope.items = ['Item1', 'Item2', 'Item3'];
})
Plnkr - http://plnkr.co/edit/D1tMRpxVzn51g18Adnp8?p=preview
There were a couple of problems.
Here is a working demo: http://plnkr.co/edit/CZPvD373HbCC2Ism0xlA?p=preview
Comments inline:
Controller
app.controller('Nav', function($scope) {
$scope.items = ['Item1', 'Item2', 'Item3'];
$scope.page = $scope.items[0];
$scope.selectItem = function (item) {
$scope.page = item;
}
})
LeftNav template
<ul>
<li ng-repeat="item in items">
<!-- calling `selectItem` on the controller to set the `page`
otherwise `page` will be set on the current `ng-include` scope
and will be unavailable elsewhere -->
{{ item }}
</li>
</ul>
RightNav template
<!-- 'page' is now from the 'Nav' controller's $scope -->
<div ng-switch on="page">
<div ng-switch-when="Item1">
<div ng-include="'Item1.html'"></div>
</div>
<!-- String matches are case sensitive -->
<div ng-switch-when="Item2">
<div ng-include="'Item2.html'"></div>
</div>
<!-- String matches are case sensitive -->
<div ng-switch-when="Item3">
<div ng-include="'Item3.html'"></div>
</div>
<div ng-switch-default>
<h1>Default</h1>
</div>
</div>

Resources