Dynamic property inside ng-if statement - javascript

<ul>
<li
ng-repeat="category in categoryList">
{{category.Name}} <br>
<ul>
<li
ng-repeat="game in gameList" ng-if="game.{{category.Name}}">
{{game.Name}}
</li>
</ul>
</li>
</ul>
I want to check if a certain game has a child with a name of the category, with the brackets it would just look up a specific child called category which doesn't exist.

in ng-if directive you can reference to variable category directly
ng-if="game[category.Name]"
angular.module('app',[])
.controller('ctrl',function($scope){
$scope.categoryList = [
{Name : '1'},
{Name : '2'},
{Name : '3'},
{Name : '4'},
{Name : '5'}
];
$scope.gameList = [
{Name : 'g1', '1':true},
{Name : 'g2', '1':true},
{Name : 'g3', '2':true},
{Name : 'g4', '7':true}
]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="category in categoryList">
Category - {{category.Name}} <br>
<ul>
<li ng-repeat="game in gameList" ng-if="game[category.Name]">
Game - {{game.Name}}
</li>
</ul>
</li>
</ul>
</div>

You may have to do that from a function in your controller. $scope.nameExists = function (game, name){return typeof game[name] !== 'undefined'; }; then ng-if="nameExists (game, category.Name)"

Related

AngularJS ng-repeat an unknown deep array

I need to have the possibility to print out a possible infinite deep array-structure into a list. Here's the code from a modified AngularJS-example where I have added some more deep children in the array. How can I print child of child and even its children as well? Is there a way I can get it to repeat forever as long as there is more children?
HTML
<div ng-app>
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<span>{{todo.text}}</span>
<ul>
<li ng-repeat="child in todo.children">
<span>{{child.text}}</span>
<!-- What about the next one -->
</li>
</ul>
</li>
</ul>
</div>
</div>
JS
function TodoCtrl($scope) {
$scope.todos = [{
text: 'root 1',
children: [{
text: 'child of root 1',
children: [{
text: 'child of child',
children: []
}]
}]
}, {
text: 'root 2',
children: []
}];
}
Fiddle: https://jsfiddle.net/U3pVM/25866/
You can use the view recursively this way:
<script type="text/ng-template" id="todo.html">
<div>
<div>{{ todo.text }}</div>
<ul>
<li ng-repeat="todo in todo.children" ng-include="'todo.html'"></li>
</ul>
</div>
</script>
<div ng-controller="MyController">
<ul>
<li ng-repeat="todo in todos" ng-include="'todo.html'"></li>
</ul>
</div>
Here the DEMO based on your sample data.

"ng-class" on each clicked item

I need to add a class on selected <li> like I have shown in demo but dont want it to be removed if I click on another <li>.
Please help
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': model.selected==item}" ng-click="model.selected=item">{{ item.name }}</li>
</ul>
</div>
JS
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.model = {
selected: null,
items : [
{name: "Apple"},
{name: "Banana"},
{name: "California"}
]
};
})
demo
Just add like this
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': selected==$index}" ng-click="selected=$index">{{ item.name }}</li>
</ul>
</div>

Collapse nested ng-repeat created divs

I am trying to achieve something like the image below. This is my data:
JS:
angular.module('app', ['angular.filter'])
.controller('MainController', function($scope) {
$scope.showReport = {};
$scope.toggleShow = function (ym) {
$scope.showReport[ym] = !$scope.showReport[ym];
};
$scope.Reports = [
{ Id: 1, Name: 'Report One', Year: 2016, Month: 5 },
{ Id: 2, Name: 'Report Core', Year: 2016, Month: 5 },
{ Id: 3, Name: 'Report Alpha', Year: 2016, Month: 3 },
{ Id: 4, Name: 'Report Moon', Year: 2015, Month: 5 },
{ Id: 5, Name: 'Report Sky', Year: 2015, Month: 2 }
];
});
HTML:
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'">
{{ key }}
<ul ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<a ng-click="toggleShow(key+key1)"> O{{key1}} </a>
<li ng-repeat="p in value1" ng-if="!showReport[key+key1]">
{{p.Name }}
</li>
</ul>
</ul>
The objective is that if you click on any of the underlined numbers, the reports that belong to that month hide or show (collapsible). That's already done. This must also happen with the years- when you click a year, the months within must show/hide. I have tried many things but it seems I cannot figure it out what I need. I have made a JS BIN where my code is.
http://jsbin.com/huhabehoju/edit?html,js,output
Any help will be kindly appreciate it. Thanks
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
<meta name="description" content="[groupBy example]"/>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div ng-controller="MainController">
<ul ng-init= "yearhide=false" ng-repeat="(key, value) in Reports | groupBy: 'Year'">
<li ng-click="yearhide = !yearhide">{{ key }}</li>
<ul ng-hide="yearhide" ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<li ng-click="hideo = !hideo">O{{key1}}
<ul>
<li ng-show="hideo" ng-repeat="p in value1">
{{p.Name }}
</li>
</ul>
</li>
</ul>
</ul>
</div>
</body>
</html>
try this jsbin link,here is demo
I have created a jsbin for you here.
I have added a new function that will hide and show the months based on your years.
$scope.showYears = {};
$scope.toggleYear = function(year) {
if ($scope.showYears[year] === undefined || $scope.showYears[year] === null)
$scope.showYears[year] = false;
else $scope.showYears[year] = !$scope.showYears[year];
}
$scope.showMonth = function(month, year) {
if ($scope.showYears[year] === undefined || $scope.showYears[year] === null)
return true;
return $scope.showYears[year];
}
The HTML has been kept as
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'">
<div ng-click="toggleYear(key)">YEAR - {{ key }}</div>
<ul ng-repeat="(key1, value1) in value | groupBy: 'Month'" ng-show="showMonth(key1, key)">
<a ng-click="toggleShow(key+key1)"> MONTH - {{key1}} </a>
<li ng-repeat="p in value1" ng-if="!showReport[key+key1]">
{{p.Name }}
</li>
</ul>
</ul>
I cant see you toggleShow method, so I am assuming that you have already written the logic for that method.
can try this one no need to add any function in controller
<div>
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'" >
<span ng-click="hideGroup[key] = !hideGroup[key]" style="cursor:pointer;">{{ key }}- {{value.show}}</span>
<ul ng-hide="hideGroup[key]" ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<span ng-click="hideGroup[key+key1] = !hideGroup[key+key1]" style="cursor:pointer;">O{{key1}}</span>
<li ng-hide="hideGroup[key+key1]" ng-repeat="p in value1">
{{p.Name }}
</li>
</ul>
</ul>
</div>
Updated:
orderBy works only for array so at first you need to convert it to array. and orderBy should be last filter and you need to add filter in your controller so inject $filter in your controller. can see this example
In Controller:
$scope.Reports= [];//your daata
$scope.showReport = {};
$scope.toggleShow = function (ym) {
$scope.showReport[ym] = !$scope.showReport[ym];
};
$scope.desc = function(arr) {
return $filter('min')
($filter('map')(arr, '-Year')); // descending by year
};
in Html:
<ul ng-repeat="reports in Reports | groupBy: 'Year' | toArray:true | orderBy:desc">
<li><span ng-click="toggleShow(reports[0].Year)" style="cursor:pointer">{{ reports[0].Year }}</span></li>
<ul ng-hide="showReport[reports[0].Year]" ng-repeat="items in reports | groupBy: 'Month'">
<li><span ng-click="toggleShow(reports[0].Year+items[0].Month)" style="cursor:pointer">O{{items[0].Month}} </span>
<ul ng-hide="showReport[reports[0].Year+items[0].Month]">
<li ng-repeat="item in items">
{{item.Name }}
</li>
</ul>
</li>
</ul>
</ul>
See Plunker Demo

Run JS on appended html with angular

Hi I want to recreate the following using angularJS.
<div>
<fieldset class="regulated">
<legend>This list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 3</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
<li>
<h4>Category2</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 2 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 2 Element 2</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
Here is how I tried and what I have achieved till now.
This is the html on which my controller is called.
<div>
<fieldset class="regulated" ng-controller="UlController2">
<legend>{{information.header}}</legend>
<ul>
<li ng-repeat="item in items">
<h4>{{item.name}}</h4>
<div ng-bind-html="element(item.followUp)"></div>
</li>
</ul>
</fieldset>
</div>
And this is the controller I am using.
app.controller('UlController2', function($scope,$sce) {
$scope.information = {
header : "This list was created with angular!"
};
$scope.items = [
{'name' : 'Category1', 'followUp' : '<ul></ul>'},
{'name' : 'Element2', 'followUp' : '<p>Description of element 2</p>'},
{'name' : 'Category2', 'followUp' : '<ul></ul>'}
];
$scope.elEments = [
{'name':'Element1','description':'Description of Category 1 Wlement 1'},
{'name':'Element2','description':'Description of Category 1 Wlement 2'},
{'name':'Element3','description':'Description of Category 1 Wlement 3'},
];
$scope.element = function(input){
return $sce.trustAsHtml(input);
}
});
I want to make this without any JQuery or native JavaScript, only AngularJS native methods.
It's not possible with the data you have there because you have no information about the category. It's also difficult for us because your variables names in the controller do not match the ones in the view. Other than that, given you have the information about the category you can do it with two nested ng-repeat.
angular.module('testApp', [])
.controller('testCtrl', ['$scope',
function($scope) {
$scope.categories = [
{
name: 'Category 1',
items: [
{
name: 'Element1',
description: 'Description of Category 1 Element 1'
},
{
name: 'Element2',
description: 'Description of Category 1 Element 2'
},
{
name: 'Element3',
description: 'Description of Category 1 Element 3'
}
]
},
{
name: 'Category 2',
items: [
{
name: 'Element1',
description: 'Description of Category 2 Element 1'
},
{
name: 'Element2',
description: 'Description of Category 2 Element 2'
},
{
name: 'Element3',
description: 'Description of Category 2 Element 3'
}
]
}
]
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="testApp" ng-controller="testCtrl">
<fieldset class="regulated">
<legend>This list was created with angular</legend>
<ul>
<li ng-repeat="category in categories">
<h4>{{category.name}}</h4>
<ul>
<li ng-repeat="item in category.items">
<h5>{{item.name}}</h5>
<p>{{item.description}}</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
I found 2 solutions, both written in angular 1.3.8.
The first is based on Marcel's answer and the other is mine.
This is based on Marcel:
app.controller('UlController2', function($scope, $sce) {
$scope.information = {
header: "This 2nd list was created with angular!"
};
$scope.items = [{
'name': 'Category1',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 1 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 1 Element 2'
}, {
'name': 'Element3',
'description': 'Description of Category 1 Element 3'
}, ]
}, {
'name': 'Element2',
'followUp': 'Description of element 2'
}, {
'name': 'Category2',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 2 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 2 Element 2'
}]
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<div>
<fieldset class="regulated long">
<legend>This 2nd list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 3</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
<li>
<h4>Category2</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 2 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 2 Element 2</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
<div>
<fieldset class="regulated long" ng-controller="UlController2">
<legend>{{information.header}}</legend>
<ul>
<li ng-repeat="item in items">
<h4>{{item.name}}</h4>
<p>{{item.followUp}}</p>
<ul>
<li ng-repeat="Li in item.innerList">
<h5>{{Li.name}}</h5>
<p>{{Li.description}}</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
And this is mine, simulating the reading of a JSON response.
app.controller('UlController3', function($scope, $sce) {
$scope.information = {
header: "This 3rd list was created with angular!"
};
var items = [{
'name': 'Category1',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 1 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 1 Element 2'
}]
}, {
'name': 'Element2',
'followUp': 'Description of element 2'
}];
$scope.innerUl = function() {
var toAdd = '';
var inner = '';
angular.forEach(items, function(value, key) {
angular.forEach(value, function(firstLiVal, key) {
if (key == 'name') {
toAdd += '<li><h4>' + firstLiVal + '</h4>';
} else if (key == 'followUp') {
toAdd += '<p>' + firstLiVal + '</p></li>';
} else if (key == 'innerList') {
angular.forEach(firstLiVal, function(SecondUlVal, key) {
angular.forEach(SecondUlVal, function(SecondLiVal, key) {
if (key == 'name') {
inner += '<li><h5>' + SecondLiVal + '</h5>';
} else {
inner += '<p>' + SecondLiVal + '</p></li>';
}
});
});
toAdd += '<ul>' + inner + '</ul></li>';
}
});
});
return $sce.trustAsHtml(toAdd);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<div>
<fieldset class="regulated long">
<legend>This 3rd list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
</ul>
</fieldset>
</div>
<div>
<fieldset class="regulated long" ng-controller="UlController3">
<legend>{{information.header}}</legend>
<ul ng-bind-html='innerUl()'></ul>
</fieldset>
</div>

How do I properly ng-repeat through nested key value pairs in angularJS

View live code:
Angular JS
How in the world do I properly loop through nested key value pairs and properly output them like below?
View I want is a tree like so
-touts
-classes
-col-12
-col-md-12
-col-lg-12
Currently the view is:
touts
{"classes":["col-12","col-md-12","col-lg-12"]}
JS:
var currentApp = angular.module('currentApp', []);
currentApp.controller('ACtrl', function($scope){
$scope.templates = {
'touts' : [
{
'classes' : ['col-12', 'col-md-12', 'col-lg-12' ]
}
]
};
});
HTML:
<div ng-app="currentApp">
<div ng-controller="ACtrl">
<ul ng-repeat="(key, prop) in templates">
<li>{{key}}</li>
<li>
<ul ng-repeat="class in templates[key]">
<li>{{class}}</li>
</ul>
</li>
</ul>
</div>
</div>
You are pretty close, I updated the fiddle. http://jsfiddle.net/y9wj6/9/
<ul ng-repeat="(key, prop) in templates">
<li>{{key}}</li>
<ul ng-repeat="val in prop">
<ul ng-repeat="(o, values) in val">
<li>{{o}}</li>
<ul ng-repeat="i in values">
<li>{{i}}</li>
</ul
</ul>
</ul>
</ul>
You must think gradually.
templates = {'touts' : [{'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }]};
// key = 'touts'
// props = [{'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }]
// props[0] = {'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }
// classkey = 'classes'
// classprop = ['col-12', 'col-md-12', 'col-lg-12' ]
// and print classprop by ng-repeat
So you can try this:
<div ng-app="currentApp">
<div ng-controller="ACtrl">
<ul ng-repeat="(key, props) in templates">
<li>{{key}}</li>
<li>
<ul ng-repeat="(classkey, classprop) in props">
<li>{{classkey}}</li>
<li>
<ul>
<li ng-repeat="class in classprop">
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
So this is pretty old question, however if you modified the object a bit (swap the array types for objects) the following template should work just fine.
angular.module('init', [])
.controller('test', ['$scope', function($scope) {
$scope.templates = {
'touts': {
'classes': {
'col-12': {},
'col-md-12': {},
'col-lg-12': {}
}
}
};
}]);
ul {
list-style: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="init" ng-controller="test">
<script type="text/ng-template" id="recursive_item.html">
{{key}}
<ul>
<li ng-repeat="(key, prop) in prop" ng-include="'recursive_item.html'"></li>
</ul>
</script>
<ul>
<li ng-repeat="(key, prop) in templates" ng-include="'recursive_item.html'"></li>
</ul>
</div>

Categories

Resources