Find sibling of current array item - javascript

This currently lists out all occurrences of the array. I only want to show the array associated for the current item in the parent array.
EG: Instead of listing First Location, Second Location, Third Location. I want it to only list First Location for the First Location, Second Location for the Second Location, etc. What am I missing?
http://plnkr.co/edit/ilgOZzIy2axSi5Iy85C7
var App = angular.module('App', []);
App.controller('locationAccordionCtrl', function ($scope) {
$scope.locations = [
{
"siteName":"First Location",
"locationsList":['First Location 1', 'First Location 2', 'First Location 3']
},
{
"siteName":"Second Location",
"locationsList":['Second Location 1', 'Second Location 2', 'Second Location 3']
},
{
"siteName":"Third Location",
"locationsList":['Third Location 1', 'Third Location 2', 'Third Location 3']
}
];
});
HTML:
<div ng-controller="locationAccordionCtrl">
<div ng-repeat="location in locations">
{{location.siteName}}
<div ng-repeat="location in locations">
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>
</div>
</div><!-- /row -->
</div>

You should change:
<div ng-repeat="location in locations">
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>
</div>
To this:
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>

Related

Vue.js + get selected li item of ul

I have a list displayed like a dropdown -
Each of the items except 'Create New Filter' is bound to a key so i can uniquely identify the li items.
I want to know how can i get the selected li item on save and do operations accordingly
What would be the good approach for this so i can understand when 'Create new filter' is clicked or when other li items are selected
Below is the code -
<ul>
<li v-on:click="create">Create New</li>
<li v-for="item in list" :key="item.id" v-on:click="Change(item.id,item.text)">{{ item.text }}</li>
</ul>
As per my understanding this approach is not good, I am not sure why you are building dropdown by using <ul> and <li> instead of select element as it is a form element and provide a better way to get the selected option value by the help of v-model directive.
Anyhow I worked as per your requirement and came up with the solution.
var app = new Vue({
el: '.dropdown',
data: {
list: [{
id: 1,
text: 'First Filter'
}, {
id: 2,
text: 'First Filter 2021'
}, {
id: 3,
text: 'Full Filter'
}],
selectedListItem: null
},
methods: {
create() {
console.log('New filter Create Called');
},
getSelected (item) {
this.selectedListItem = item;
},
save() {
if (this.selectedListItem) {
console.log(this.selectedListItem);
} else {
console.log('No list option selected');
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<div class="dropdown">
<input type="text" placeholder="Select Filter" class="dropdown-toggle" data-toggle="dropdown"/>
<ul class="dropdown-menu">
<li v-on:click="create">Create New</li>
<li v-for="item in list" :key="item.id" v-on:click="getSelected(item)">{{ item.text }}</li>
</ul>
<button #click="save">SAVE</button>
</div>

Issue when trying to add popup menu with multi level sub menu in Vuejs?

data: {
menuItems: [{
name: 'Item 1',
children: [{
name: 'Subitem 1'
}, {
name: 'Subitem 2'
}, {
name: 'Subitem 3'
}]
},
{
name: 'Item 2'
}
],
selectedDropdown: 'None'
},
methods: {
setSelectedItem(item) {
this.selectedDropdown = item;
}
},
ready: function() {
$('.dropdown-submenu a.test').on("click", function(e) {
$(this).next('ul').toggle();
e.stopPropagation();
e.preventDefault();
});
}
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
<ul>
<li :class="{ current : item === value }" v-for="item in list" #click="select(item)">{{ item }}</li>
</ul>
<ul class="dropdown-menu" v-if="item.children">
<li v-for="child in item.children"><a tabindex="-1" href="#" #click="setSelectedItem(child.name)">{{child.name}}</a></li>
CodePen link https://codepen.io/santoshch/pen/mdWwepg
Tried adding sub menu in the dropdown, But unable to do that, i mean multi level dropdown. Taken one more ul and li tag to display items, But not sure how to proceed.
In the data i have already passed items and value, But for sub multi level i need to add few items.
For the above codepen, Tried to add code for sub multi level items, Then i am getting error
You could extend your array list (from your codepen example) with objects:
list: [
'Orange',
'Apple',
'Kiwi',
'Lemon',
'Pineapple',
{
name: 'Others',
children: [
'Strawberries',
'Raspberries',
'Blueberries'
]
},
'Last Fruit'
]
And when you loop over the list you check for these objects and output them in a nested <ul> element:
<ul>
<template v-for="(item, index) in list">
<li v-if="item.name" :key="index" :class="{ current : item === value }">
{{ item.name }}
<ul>
<li v-for="(childItem, childIndex) in item.children" :class="{ current : childItem === value }" :key="childIndex" #click="select(childItem)">
{{ childItem }}
</li>
</ul>
</li>
<li v-else :key="index" :class="{ current : item === value }" #click="select(item)">{{ item }}</li>
</template>
</ul>
Here is a working example (without styling the submenu)
https://jsbin.com/caroguwori/edit?html,js,output

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.

jquery click event is not working with angular.js ng-repeat

I have a nested (tertiary) menu list with a jquery click event on the back. jQuery click does not fire when the menu item is clicked. The jQuery event works well if the values inside the HTML are static.
HTML:
<div>
<ul class="collapsible-list" ng-controller="ViewCtrl">
<li class="collapsible-list-subnav" ng-repeat="view in views">
<a class="collapsible-list-parent">{{view.name}}</a>
<ul class="collapsible-list secondary">
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent">Public Views</a>
<ul class="collapsible-list tertiary">
<li ng-repeat="publicview in view.publicviews">
<a>{{publicview.title}}</a>
</li>
</ul>
</li>
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent">Private Views</a>
<ul class="collapsible-list tertiary">
<li ng-repeat="privateview in view.privateviews">
<a>{{privateview.title}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Javascript:
define([ 'angular', 'controllers-module'], function(angular,
controllers) {
controllers.controller("ViewCtrl", [
"$scope",
"$rootScope",
"directiveBinder",
'$timeout',
'$stateParams',
'$resource',
'$state',
function($scope, $rootScope,directiveBinder, $timeout, $stateParams, $resource, $state) {
$scope.engines = [ {
name : 'name1',
publicviews : [ {
title : 'First public View'
} ],
privateviews : [ {
title : 'First private View'
} ]
}, {
name : 'name2',
publicviews : [ {
title : 'Second public View'
} ],
privateviews : [ {
title : 'Second private View'
} ]
} ];
$('.collapsible-list-parent').click(function(e) {
e.preventDefault();
$(this).next().slideToggle('fast');
if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open');
} else {
$(this).parent().addClass('open');
}
});
});
Because the elements are added dynamically by ng-repeat the .click event is not binded to them. Try to use .delegate
$( "ul" ).delegate( ".collapsible-list-parent", "click", function() {
// code here
});
When we use ng-repeat and need to trigger a jquery click event just try this it worked for me.
$(document).on("click", ".className", function() {
//your code here...
});
I don't think using jQuery code in an angularjs controller is the right way to do this, a sample to do the same without the animation will be like
var app = angular.module('my-app', [], function() {
})
app.controller('ViewCtrl', function($scope) {
$scope.views = [{
name: 'name1',
publicviews: [{
title: 'First public View'
}],
privateviews: [{
title: 'First private View'
}]
}, {
name: 'name2',
publicviews: [{
title: 'Second public View'
}],
privateviews: [{
title: 'Second private View'
}]
}];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app">
<ul class="collapsible-list" ng-controller="ViewCtrl">
<li class="collapsible-list-subnav" ng-repeat="view in views">
<a class="collapsible-list-parent" ng-click="open = !open">{{view.name}}</a>
<ul class="collapsible-list secondary" ng-show="open">
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent" ng-click="popen = !popen">Public Views</a>
<ul class="collapsible-list tertiary" ng-show="popen">
<li ng-repeat="publicview in view.publicviews">
<a>{{publicview.title}}</a>
</li>
</ul>
</li>
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent" ng-click="ropen = !ropen">Private Views</a>
<ul class="collapsible-list tertiary" ng-show="ropen">
<li ng-repeat="privateview in view.privateviews">
<a>{{privateview.title}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
If you want to use animations you can make use of angularjs animation which uses css3 animations.

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>

Categories

Resources