Array in array, angularJS, ng-repeat - javascript

im struggling with iterating over arrays in arrays. I need to create buttonlike vertical menu and cant get it work.
angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = [
'Home',
'Orders':
{
orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']
},
'Users',
'Resources',
'Settings',
'Help'
];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">{{ item }}
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
What i need to do is display array of items and while Orders item is active expand it with elements given in other array. To be honest i just dont know how to make it.

You are trying to ng-repeat over a heterogeneus array. i.e. it's elements are not all of the same type. The implementation logic needs to change here.
One thing you can do if your data structure is not flexible, is to use a typeof item === 'object' to filter out the object from the strings, or conversely check for typeof string

Here's a quick, basic example of what you could use:
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: [{
name: 'Orders'
}]
},{
name: 'Users'
},
...
];
<li ng-repeat="item in items | filter:filterQuery" class="btn btn-lg list-group-item dropdown" ng-class="{active: activeMenu === item}" ng-click="setActive(item)">
<a aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" class="dropdown-toggle" href="#">
{{ item.name }} <span class="caret" ng-if="item.dropdown"></span>
</a>
<ul ng-if="item.dropdown" class="dropdown-menu">
<li ng-repeat="dItem in item.dropdown">
{{dItem.name}}
</li>
</ul>
</li>
I'd suggest having another indepth look at https://docs.angularjs.org/api/ng/directive/ngRepeat to fully understand the structure required by the directive.

angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = {
main:['Home','Orders','Users','Resources','Settings','Help'],
sub:['Open','Closed','New','Forgotten']
};
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items.main | filter:filterQuery">{{ item }}
<ul>
<li class="btn btn-lg list-group-item" ng-repeat="it in items.sub" ng-if="activeMenu === 'Orders'">{{it}}</li>
</ul>
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
This is closer to what i want to achieve. But i dont know how to apply this nested UL to only one Li from parent list.

this filter work correctly
INPUT :
['Home',{ 'Orders':{orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']}},'Users','Resources','Settings','Help']
OUTPUT :
["Home", "Orders", "Open", "Closed", "New", "Forgotten", "Users", "Resources", "Settings", "Help"]
app.filter('customfilter', function () {
return function (data) {
function clean(item)
{
var result = [] ;
// check if type is array
if(Array.isArray(item)){
// parse array
item.forEach(function(i){
result = result.concat(clean(i));
})
}// check if type is opject
else if(typeof item =="object"){
// parse opject
Object.keys(item).map(function (key) {
result = result.concat(clean(item[key]));
});
}else{
result= [item]
}
return result ;
}
return clean(data) ;
}
})

I believe there are so many ways to answer this question,although I've made a sample plunker for your problem.Below is how your
HTML will look like
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">
<a href="#">
<p ng-hide="item.dropdown"> {{ item.name }}</p>
<p ng-show="item.dropdown" ng-repeat="values in item.dropdown"> {{ values }}</p>
</a>
</li>
</ul>
</div>
</div>
</body>
JS look like
angular.module('NavigationApp', []).controller('NavigationController', function($scope) {
var orderItemsObj = {
orders: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
};
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
}, {
name: 'Users'
}, ];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});

Related

How to assign v-on dinamically with v-for

I have a code in Vue that creates the elements of a menu using a v-for, and each element must have a different method when it's clicked.
So far I have this:
<span v-for="(menuItem, index) in menuItems" :key="index">
<li>
<a id="listItem">
<i class="bx" :class="menuItem.icon || 'bx-square-rounded'" />
<span class="links_name" v-on:click=menuItem.click>{{ menuItem.name }}</span>
</a>
<span class="tooltip">{{
menuItem.tooltip || menuItem.name
}}</span>
</li>
</span>
How can I assign different funcions on the v-on?
You can make the listener function as a node in the object list.
Sample Implementation
const app = new Vue({
el: '#app',
data() {
return {
list: [{
name: 'lg',
age: 27,
onClick: function() {
console.log("First Item Clicked");
}
}, {
name: 'camile',
age: 27,
onClick: function() {
console.log("Second Item Clicked");
}
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list" :key="item.name">
{{item.name}} - {{item.age}}
<button #click="item.onClick()">
Click Me
</button>
</li>
</ul>
<input type="text" v-model="list[0].name">
</div>
</body>

Pass array into ng-click

http://jsfiddle.net/u0jzkye1/
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items">{{item.name}}</li>
</ul>
<button type="submit" ng-click="send()">
Send
</button>
</div>
When the button is not within ng-repeat, how can I pass my item's id into ng-click function?
Well items is already on $scope as you're using it in your ng-repeat. So you should simply be able to ng-click="send(items)"
var items = [{
id: 1,
name: "one"
}, {
id: 2,
name: "two"
}];
function MyCtrl($scope) {
$scope.items = items;
$scope.send = function() {
//get items' id
$scope.items.forEach(function(item){
alert(item.id);
}, this);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items">{{item.name}}</li>
</ul>
<button type="submit" ng-click="send()">
Send
</button>
</div>

ui-bootstrap Angular modal resolve and Scope value

I am relatively new to angular and I have integrated Bootstrap modal to my project but I am not able to use the value from "programcontroller".
I want id_program from "programcontroller" inside the "ModalInstanceCtrl" controller. I tried adding it in the RESOLVE but I was not able to get the data.
I got the hardcoded data using the RESOLVE from "programcontroller" successfully inside "ModalInstanceCtrl" controller of modal.
But since I get the id_prgram using this snipet:
<input type="text" ng-hide=" true" ng-model="id_program" ng-init="id_program=item._id">
The above code is inside ng-repeat block and gets populated. I do know that it is because of asynchronous that causes the problem.
I have attached the code for your reference.
catalogapp.controller('programcontroller', function ($scope, $uibModal, $log, $routeParams) {
$scope.id_program = "";
$scope.title_program = "";
$scope.filter_program = $routeParams.seasonId;
$scope.season_number = $routeParams.seasonNumber;
$scope.model = {
//got this from previous HTML page as routeparams
season_id : $routeParams.seasonId
}
$scope.animationsEnabled = true;
$scope.program_array = [
{
"_id" : "program:a8097ae943bdbd372906ea494ddecbf2",
"series" : "series:fcde9691e624ba50df9be71735f4bb14",
"title" : "title1",
"season" : "season:a6e4d728c316cdffa933490d4f538251",
},
{
"_id" : "urn:esp:hbo:program:testprogram20160310",
"title" : "title1",
"series" : "series:4f19358c7377482f1310e5cfa06c5bd2",
"season" : "season:a6e4d728c316cdffa933490d4f538251",
}
]
$scope.items = [
{
"title" : "title",
"_id" : "program:version:2541203f297f8f0d",
"shortTitle" : "shtitle",
"program" : "program:f555feb8dafc1bae42d",
},
{
"title" : "title2",
"_id" : "program:version:40a2313f297f8f0d",
"shortTitle" : "shtitle2",
"program" : "program:f55asfsa57927411bd6545feb8dafc1bae42d",
},
{
"title" : "title3",
"_id" : "program:version:403f297f8f0d",
"shortTitle" : "shtitle3",
"program" : "program:asdf5557927411bd6545feb8dafc1bae42d",
}
]
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
backdrop: 'static',
resolve: {
items1: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
}
});
catalogapp.controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items1) {
$scope.items = items1;
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
HTML Code is given below!!!!
<!doctype html>
<html>
<head>
<title>HBO ESP Console</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular-route.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/main.css">
<script src="/controllers/programcontroller.js"></script>
</head>
<body style="background-color:#44484a">
<h2>Program List</h2>
<script type="text/ng-template" id="myModalContent.html">
<body ng-controller="ModalInstanceCtrl">
<div class="modal-header">
<h3 class="modal-title">Program Version</h3>
</div>
<div class="modal-body" style="float:left">
<ul ng-repeat="item in items" style="list-style-type:none">
<li class="image">
<button type="button" style="background-color: #555555" class="btn btn-default">
<img ng-src="http://icons.iconarchive.com/icons/atti12/tv-series-folder/512/Game-of-Thrones-icon.png" height="200" width="200" />
</button>
</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</body>
</script>
<div ng-controller="programcontroller">
<input ng-hide=" true" type="text" ng-model="filter_program"><br><br>
<p ng-hide=" true">Season_id: {{model.season_id}}</p>
<p style="font-size:18px">Season Number:{{season_number}}</p>
<div style="float:left">
<div style="float:left">
<ul ng-repeat=" item in program_array | filter : filter_program" style=" list-style-type:none;float:left">
<li class="image">
<input type="text" ng-hide=" true" ng-model="id_program" ng-init="id_program=item._id">
<input type="text" ng-hide=" true" ng-model="title_program" ng-init="title_program=item.title">
<button type="button" style="background-color: #555555" class="btn btn-default" ng-click="open('lg')">
<img ng-src="http://icons.iconarchive.com/icons/atti12/tv-series-folder/512/Game-of-Thrones-icon.png" height="200" width="200" />
</button>
<p>{{item.title}}</p>
{{id_program}}
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
PLEASE help me with this guys!!!!!! Thanks
You are trying to access the filter value even before angular has processed it.
Here is the solution
<ul ng-repeat="it in itm">
<li>
{{it._id}}
<input type="text" ng-hide="true" >
<button type="button" class="btn btn-default" ng-click="setFilter(it._id);open('lg')">Large modal --- {{it._id}}</button>
</li>
</ul>
Controller
$scope.setFilter = function (filterValue) {
$scope.filter = filterValue;
}
Here is the Plunkr
Hope this helps!!
remove ng-controller="ModalInstanceCtrl" from
<script type="text/ng-template" id="myModalContent.html">
and see what happens.

angularjs tutorial code debug

im learning angularjs thru an Apress book and I've come across some code that doesnt work, ive tried to debug but my console isnt giving me any errors or anything. Maybe some experts can guide me thru whats wrong, thanks.
customFilters.js file
// Creating a custom filter
// arguments for the filter method is unique and a factory function that returns a filter function that does the actaul work
angular.module('customFilters',[]).filter('unique', function() {
return function(data, propertyname) {
if (angular.isArray(data) && angular.isString(propertyname)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyname];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
sportsStore.js file
//declaring a dependency called customFilters that contains a unqiue filter
angular.module('sportsStore',['customFilters']);
// calling the angular.module method passing in sportsStore located in app.html
angular.module('sportsStore').controller('sportsStoreCtrl', function($scope) {
$scope.data = {
products: [
{name: "Product 1", description:"A product", category:"Category #1", price: 100},
{name: "Product 2", description:"A product", category:"Category #1", price: 110},
{name: "Product 3", description:"A product", category:"Category #2", price: 210},
{name: "Product 4", description:"A product", category:"Category #3", price: 202}
]
};
});
my productListControllers.js file
angular.module('sportsStore').controller('productListCtrl', function($scope,$filter){
var selectedCategory = null;
$scope.selectedCategory = function(newCategory) {
selectedCategory = newCategory;
};
$scope.categoryFilterFn = function(product) {
return selectedCategory == null || product.category == selectedCategory;
};
});
app.html file
<!DOCTYPE html>
<!-- We are defining the sportStore module here in the html tag-->
<html ng-app="sportsStore">
<head>
<title>Sports Store</title>
<link href="bootstrap.min.css" rel="stylesheet" />
<link href="bootstrap-theme.min.css" rel="stylesheet" />
</head>
<!-- Applying ng-controller to the body tagg -->
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">Sports Store</a>
</div>
<div class="panel panel-default row" ng-controller="productListCtrl">
<div class="col-xs-3">
<a class="btn btn-block btn-default btn-lg" ng-click="selectCategory()">Home</a>
<!-- generating the navigation elements here -->
<a class="btn btn-block btn-default btn-lg" ng-repeat="item in data.products |orderBy:'category'| unique:'category'" ng-click="selectCategory(item)">{{item}}</a>
</div>
<div class="col-xs-8">
<!-- ng-repeat generates elements for each object in an array -->
<!-- we also create a local variable called item -->
<div class="well" ng-repeat="item in data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">{{item.price | currency}}</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
<script src="angular.js"></script>
<script src="controllers/sportsStore.js"></script>
<script src="filters/customFilters.js"></script>
<script src="controllers/productListControllers.js"></script>
</body>
</html>
You have a typo in your html file. The function is selectedCategory not selectCategory.
There is a typo, the template says selectCategory and the controller says selectedCategory

AngularJS: Error: Unknown provider

Simple thing - works in the jsfiddle but not in my file. I'm trying to add some data to "factory" of the module and then use it within my controllers.
This is the relevant code:
var challengesApp = angular.module('challengesApp', []);
challengesApp.factory('Challenges', function() {
var challenges = [
{
'program': {
"num": "1",
"name": "aaa"
},
'challengeDesc': "desss",
'items': [
{title:"aaa",
desc:"bbb",
link: "www.google.com",
fiction: true},
]
}
];
return challenges;
});
function ChallengeCtrl($scope, Challenges) {
$scope.challenges = Challenges;
etc...
}
function ChallengeListCtrl($scope, Challenges) {
$scope.challenges = Challenges;
etc..
}
and the HTML:
<body ng-app="challengesApp">
<div ng-controller="ChallengeCtrl">
<div id="question">
<h2>{{ challenge.challengeDesc }}</h2>
<ul>
<li ng-repeat="item in challenge.items">
<strong>{{ item.title }}</strong> - {{ item.desc }}
</li>
</ul>
</div>
</div>
<div ng-controller="ChallengeListCtrl">
<div id="programs_list">
<ul>
<li ng-repeat="program in challenges | orderBy:orderProp:reverse">
<a href="" ng-click="changeChallenge(program)">
{{ program.program.num }} - {{ program.program.name }}
</a>
</li>
</ul>
</div>
</div>
<script src="js/main.js"></script>
</body>
anything here that I'm missing?
So, as I suspected, it was a dumb mistake. the <html> tag was:
<html ng-app>
blocking the correct ng-app attribute at the <body> tag.

Categories