Collapse nested ng-repeat created divs - javascript

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

Related

toggle show/hide of list items using angularjs

var myApp = angular
.module("myApp", [])
.controller("listController", function($scope) {
var foodList = [
{ name : 'Hyderbadi Koma',
types : [
{ name : "sweet" },
{ name : "extra chatpata" },
{ name : "chatpata" }
],
flag: 0
}]; ...
$scope.showhide = function(foodLists) {
if (foodLists.flag == 0)
foodLists.flag++;
else
foodLists.flag--;
};
});
...
<td class="leftSection">
<ul>
<li ng-repeat="foodItem in foodList" ng-click="showhide(foodItem)" class="clic">
{{ foodItem.name }}
<ul>
<li ng-repeat="foodType in foodItem.types" ng-hide="{{ foodItem.flag | filtering }}" class="unclic">
{{ foodType.name }} ///For watching variable flag {{foodItem.flag}}
</li>
</ul>
</li>
</ul>
...
Now here after tracing i found that "ng-click" is performing its action of changing the flag value from 1 to 0 and vice versa. Though I am not able to debug why ng-hide is not performing its action simultaneously, please help!
try this...
<td>
<ul ng-repeat="foodItem in foodList">
<li class="clic">
{{ foodItem.name }}
<ul ng-repeat="foodType in foodItem.types">
<li ng-hide="{{ foodItem.flag}}" class="unclic">
{{ foodType.name }}
</li>
</ul>
</li>
</ul>
</td>
https://plnkr.co/edit/sTWHI3SQeKgNN7QoOrrw

"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>

angularjs: check length of filter in ng-repeat

For example i have this repeat list:
<ul>
<li class="suggestion-item" ng-repeat="item in suggestionList.items | filter: {id: 2} track by track(item)">{{item.text}}</li>
<ul>
Can i somehow (would be better without changing controller because it's a directive) check: if filter result is not empty - then display whole ul, if not, then hide ul. I mean something like:
<ul ng-if="(item in suggestionList.items | filter: {id: 2}).length > 0">
<li class="suggestion-item" ng-repeat="item in suggestionList.items | filter: {id: 2} track by track(item)">{{item.text}}</li>
<ul>
You can assign the filter result to a variable
<ul ng-show="filterResult && filterResult.length">
<li class="suggestion-item" ng-repeat="item in filterResult = (suggestionList.items | filter: {id: 2}) track by track(item)">{{item.text}}</li>
<ul>
using $parent you can achieve it
<ul ng-show="suggestionListItem.length" >
<li class="suggestion-item" ng-repeat="item in ($parent.suggestionListItem = (suggestionList.items | filter: {id: 2} track by track(item)))">{{item.text}}</li>
<ul>

Is this possible with AngularJS?

Trying to execute the following code, using AngularJS.
So far I got this:
<ul>
<li ng-repeat='(key,value) in dset'><span>{{key}}</span>
<li ng-repeat="n in value"> {{ n }}</li> //DOES NOT WORK
</li>
</ul>
dSet: { "something" : [ "abc, "def" ], "something2": ["abc","blah"] }
Basically I have a Map> and want to print this as in:
String1
listValue1
listValue2
listValue3
...
String2
listValue1
listValue2
Please let me know if you have any thoughts on how to get this to work.
Suppose your dset is...
$scope.dset = {a: [1,2,3], b: [4,5,6]};
If you want your list-items to be nested, use:
<ul>
<li ng-repeat="(key, val) in dset"><span>{{key}}</span>
<ul><li ng-repeat="v in val">{{v}}</li></ul>
</li>
</ul>
If you want your list-items not to be nested, use ng-repeat-start and ng-repeat-end:
<ul>
<li ng-repeat-start="(key, val) in dset"><span>{{key}}</span>
<li ng-repeat="v in val" ng-repeat-end>{{v}}</li>
</ul>

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