Recursive template Angular2 - javascript

How can I do recursive template with Angular 2 without ng-include. I don't understand why Angular 2 won't include this skill...
HTML:
<div ng-app="app" ng-controller='AppCtrl'>
<script type="text/ng-template" id="categoryTree">
{{ category.title }}
<ul ng-if="category.categories">
<li ng-repeat="category in category.categories" ng-include="'categoryTree'">
</li>
</ul>
</script>
<ul>
<li ng-repeat="category in categories" ng-include="'categoryTree'"></li>
</ul>
JS:
var app = angular.module('app', []);
app.controller('AppCtrl', function ($scope) {
$scope.categories = [
{
title: 'Computers',
categories: [
{
title: 'Laptops',
categories: [
{
title: 'Ultrabooks'
},
{
title: 'Macbooks'
}
]
},
{
title: 'Desktops'
},
{
title: 'Tablets',
categories: [
{
title: 'Apple'
},
{
title: 'Android'
}
]
}
]
},
{
title: 'Printers'
}
];
});

Use ngFor instead of ng-repeat in Angular2.
https://angular.io/docs/ts/latest/api/common/NgFor-directive.html

Related

Recursive directive in angular js

I created a custom directive.
angular.module('menu',[])
.directive('Menu',function(){
return{
restrict:'E',
replace:'true',
scope:{
menuList:'=',
id:'#',
parentId:'#'
},
controller:function($scope){
},
template: `
<div ng-repeat="menuItem in menuList">
<a>{{menuItem.longDescription}}</a>
<div ng-if="menuItem.child.size() > 0 ">
<menu menu-list="menuItem.child"
id="menuItem.optionGroupId"
parent-id="menuItem.parentOptionGroupId">
</menu>
</div>
</div>
`
}
})
Menu items can have child list and if child list exist it should make menu recursively, but recursion is not happening.
(function() {
angular.module("menuTest", [])
.controller('testCtrl', function($scope) {
$scope.menu = [{
id: 1,
children: [{
id: 3
}]
},
{
id: 2,
children: [{
id: 4
},
{
id: 5
}
]
}
];
})
.directive("menu", function() {
return {
restrict: "E",
replace: true,
scope: {
menuList: '='
},
template: '<div ng-repeat="menuItem in menuList">{{menuItem.id}}<div ng-if="menuItem.children && menuItem.children.length>0" ><menu menu-list="menuItem.children"></menu></div><div>'
}
})
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="menuTest" ng-controller="testCtrl">
<menu menu-list="menu"></menu>
</div>

Filter with ng-repeat

I'm trying to make a filter with the angularJs directive called ng-repeat the filter works as follows:
When you click on the checkbox filters in an array the items that have offers, I'm using a function to filter, I think there is a better way to do it without so much code.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.items = [
{
id: 0,
description: "Primer Item 1",
offers: [
{
id: 0,
name: "Casa"
}
]
},
{
id: 1,
description: "Segundo Item 2"
},
{
id: 2,
description: "Tercer Item 3"
},
{
id: 3,
description: "Cuarto Item 4"
},
{
id: 4,
description: "Quinto Item 5"
},
{
id: 5,
description: "Sexto Item 5",
offers: [
{
id: 1,
name: "Bodega"
}
]
},
{
id: 6,
description: "Septimo Item 6"
},
{
id: 7,
description: "Octavo Item 7"
},
{
id: 8,
description: "Noveno Item 8"
},
{
id: 9,
description: "Decimo Item 9"
}
];
$scope.filterItem = function() {
if (!$scope.itemOffer){
$scope.filterOffer = function(item) {
return item.offers && item.offers.length > 0;
};
$scope.itemOffer = true;
} else {
$scope.filterOffer = function(item) {
return item;
};
$scope.itemOffer = false;
}
};
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" name="filter" value="propertyOffer" ng-model="propertyOffer" ng-click="filterItem()">Item with offert
<div ng-repeat="item in items | filter: filterOffer track by $index">
{{ item }}
</div>
</body>
</html>
You can use ng-if with the ng-repeat directive to filter items containing offers at will :
JS CODE
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.offersOnly = false;
$scope.items = [
// Your items
];
});
HTML CODE
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" ng-model="offersOnly" ng-true-value="true" ng-false-value="false"/>
<div ng-repeat="item in items" ng-if="!offersOnly">
{{item}}
</div>
<div ng-repeat="item in items" ng-if="offersOnly && item.offers">
{{item}}
</div>
</body>

How do I get the real index of this user in my array?

I'm getting my example from Vue JS docs
If I have a v-for that's filtered, how do I get the real index of this user in my array? Not the index of the current iteration, but the index of the item from the array.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ $index }} <!--I want Jim's index to be 3, not 0-->
</li>
</ul>
</div>
Vue JS:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
}
})
This should do it:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
},
methods : {
getIndexOfItem: function(arr, item) {
return arr.indexOf(item);
}
}
});
<script src="https://unpkg.com/vue#next/dist/vue.js"></script>
<div id="filter-by-example">
<ul>
<li v-for="user in users">
{{getIndexOfItem(users, user)}} - {{user.name}}
</li>
</ul>
</div>
Added a getIndexOfItem method into the methods collection and in the v-for passed in the array and item then returned the item index, this seems complex but most other implementations didn't seem to work work.
Edit 2
I removed the function inside the methods collection.
<li v-for="(user, index) in users | filterBy 'Jim' in 'name'">
https://jsbin.com/misagagewo/edit?output
As far as I know you can't. You can do something like this though.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ user._index }}
</li>
</ul>
</div>
JS:
function fixupObjArray(arr) {
arr.forEach((e,i) => e._index = i);
return arr;
}
new Vue({
el: '#filter-by-example',
data: {
users: fixupObjArray( [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
] )
}
})

Hide Empty Filtered ng-repeat

I am looking to hide a category if it it empty. My current solution is not working:
HTML:
<ul>
<li data-ng-repeat="items in shop | unique : 'cat' | orderBy: 'cat'">
<h2>{{items.cat}}</h2>
<ul>
<li ng-repeat="items in shop | filter:{cat: items.cat} | filter:query"
<h3>{{items.name}}</h3>
</li>
</ul>
</li>
</ul>
My Filter "unique" looks like so:
app.filter('unique', function() {
return function(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
});
JSON:
{
"businesses" : {
"-KQ1ggyrnYGYL1084Htz" : {
"name" : "business name",
"cat" : "food",
},
}
I assume that I could do something with ng-if and/or ng-hide/show but none of the combos I have done work.
You can use the ngIf directive or the ngShow/ngHide directives.
How you use them depends on your JSON.
Heres an example of the ngIf with some basic data:
(function() {
angular.module('MyApp', []);
})();
(function() {
angular.module('MyApp').controller('MyController', MyController);
MyController.$inject = ['$scope'];
function MyController($scope) {
$scope.shop = [{
name: "test 1",
cat: "cat 1"
}, {
name: "test 2",
cat: "cat 3"
}, {
name: "test 3",
cat: ""
}, {
name: "test 4",
cat: "cat 4"
}];
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="MyApp">
<div data-ng-controller="MyController">
<ul>
<li data-ng-repeat="items in shop | orderBy: 'cat'" ng-if="items.cat">
<h2>{{items.cat}}</h2>
<ul>
<li ng-repeat="items in shop | filter:{cat: items.cat}">
<h3>{{items.name}}</h3>
</li>
</ul>
</li>
</ul>
</div>
</div>

How to implement here hiding and displaying items in the list?

I found a code that outputs a multi-level list into Angular here
http://jsfiddle.net/c4Kp8/
var items = [{
title: 'Something',
children: [
{ title: 'Hello World' },
{ title: 'Hello Overflow' },
{ title: 'John Doe', children: [
{ title: 'Amazing title' },
{ title: 'Google it' },
{ title: 'Im a child', children: [
{ title: 'Another ' },
{ title: 'He\'s my brother' },
{ title: 'She\'s my mother.', children: [
{title: 'You never know if im going to have children'}
]}
]}
]}
]
}];
var app = angular.module('app', []);
app.controller('test', function( $scope ) {
$scope.items = items;
});
app.directive('nestedItem', ['$compile', function($compile){
return {
restrict: 'A',
link: function(scope, element){
console.log(element);
if (scope.item.children){
var html = $compile('<ul><li nested-item ng-repeat="item in item.children">{{item.title}}</li></ul>')(scope);
element.append(html);
}
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="test">
<ul>
<li nested-item ng-repeat="item in items">{{item.title}}</li>
</ul>
</div>
How to implement here hiding and displaying items in the list? Only Angular not jquery....
Hope you know that, you can make nested ng-repeat without special directive for it :-) ?
You can use for example angular-ui.bootstrap.collapse, or some custom solutions.
Solutions:
Angular UI Bootrap
Googled custom solution
Use ng-show / ng-hide / ng-if
https://docs.angularjs.org/api/ng/directive/ngShow
https://docs.angularjs.org/api/ng/directive/ngHide
https://docs.angularjs.org/api/ng/directive/ngIf
Maybe a treeview is more adequate than multiples imbricated ng-repeat
http://ngmodules.org/modules/angular.treeview

Categories