OK I am fairly new to VueJS, but I am not sure what I am missing here. We have navigation of categories that goes 3 levels deep. I am trying to output the 3rd level of nested navigation and it isnt working as i would expect.
This is the JSON I am using to test with, The data I am trying to use is under children then child.
return {
navList: [
{ id: 1, type: 'Item', url: "#", name: "About Us", target: '_blank' },
{ id: 2, type: 'Item',url: "#", name: "Story", target: '_blank' },
{ id: 3, type: 'Item',url: "#", name: "Price", target: '_blank' },
{
id: 4,
type: 'Item',
url: "#",
name: "Services",
target: '_blank',
children: [
{
url: "https://twitter.com/",
name: "Twitter",
target: "_blank",
child: [
{
url: "https://twitter.com/",
name: "Twitter",
target: "_blank",
},
{
url: "https://dribbble.com/",
name: "Dribbble",
target: "_blank"
},
{
url: "https://www.behance.net/",
name: "Behance",
target: "_blank"
},
],
},
{
url: "https://dribbble.com/",
name: "Dribbble",
target: "_blank"
},
]
},
]
};
},
And here is the code for my navigation.
I am trying to loop through using item.children.child but for some reason it is outputting "Service" see screen shot below.
<template>
<nav class="navbar navbar-light navbar-expand-lg mainmenu">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav mr-auto">
<li v-for="item in navList" :key="item.id" class="dropdown">
<template v-if="item.children">
<a class="dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
:id="item.name"
:href="item.url"
:title="item.name"
#click="show = !show">{{ item.name }}
</a>
<ul class="dropdown-menu"
:class="{ show }"
:aria-labelledby="item.name">
<li class="dropdown-item" v-for="{ url, name, index, target } in item.children" :key="index" >
<a class="dropdown-toggle" role="button" aria-haspopup="true" aria-expanded="false"
:href="url"
:title="name"
:target="target"
:data-toggle="name">
{{ name }}
</a>
<ul class="dropdown-menu"
:aria-labelledby="name">
<template v-if="item.children.child">
<li class="dropdown-item" v-for="{ url, name, index, target } in item.children.child" :key="index" >
<a class="dropdown-toggle" role="button" aria-haspopup="true" aria-expanded="false"
:href="url"
:title="name"
:target="target"
:data-toggle="name">
{{ name }}
</a>
</li>
</template>
<template v-else>
<a class="nav-link"
:href="item.url"
:title="item.name"
:target="item.target"
>{{ item.name }}</a>
</template>
</ul>
</li>
</ul>
</template>
<template v-else>
<a class="nav-link"
:href="item.url"
:title="item.name"
:target="item.target"
>{{ item.name }}</a>
</template>
</li>
</ul>
</div>
</nav>
</template>
The problem will be the v-for="{ url, name, index, target } in item.children". With v-for, you can either use v-for="item in items" or v-for="(item, index) in items" syntax (talking about arrays). You actually are using the first one here and this means you are trying to destructure { url, name, index, target } properties from your items. This causes the index to be undefined as your items do not have such property on them, and because of that your list items no longer have unique :key property. Try instead this:
v-for="({ url, name, target }, index) in item.children"
For More Info: https://v2.vuejs.org/v2/guide/list.html
Related
Here is an working example https://jsfiddle.net/79epsrmw/
But same in vs code not targeting to item1 sub menu, After passing unique id also.
var app = new Vue({
el: '#app',
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;
}
<div class="container" id="app">
<h2>Vue.js multi-level dropdown example</h2>
<p>
Selected element: {{ selectedDropdown }}
</p>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">Dropdown
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li v-for="item in menuItems" v-bind:class="{'dropdown-submenu': item.children}">
<a class="test" tabindex="-1" href="#">{{item.name}}<span class="caret" v-if="item.children"></span></a>
<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>
</ul>
</li>
</ul>
</div>
</div>
I am getting an error ""Elements in iteration expect to have 'v-bind:key' directives.eslint-plugin-vue
So in order to clear the error i have taken key and passed unique id to it
{{child.name}}
So in order to clear the error i have taken key and passed unique id to it. like :key="child"
Issue is in editor it is working fine, But in vs code after passing unique id, I am unable to select the sub menu in item1.
Check this fiddle
https://jsfiddle.net/negqvmjd/35/
var app = new Vue({
el: '#app',
data: function () {
return {
menuItems: [
{
name: 'Item 1',
children: [{name: 'Subitem 1'},{name: 'Subitem 2'},{name: 'Subitem 3'}]
},
{
name: 'Item 2',
children: []
}
],
selectedDropdown: 'None'
}
},
methods: {
setSelectedItem(item,childLength, bool) {
if(childLength === 0 && bool === false){
this.selectedDropdown = item;
}
else if(childLength !==0 && bool === true){
this.selectedDropdown = item;
}
}
},
ready: function() {
$('.dropdown-submenu a.test').on("click", function(e){
$(this).next('ul').toggle();
e.stopPropagation();
e.preventDefault();
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container" id="app">
<h2>Vue.js multi-level dropdown example</h2>
<p>
Selected element: {{ selectedDropdown }}
</p>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">Dropdown
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li v-for="item in menuItems" v-bind:class="{'dropdown-submenu': item.children.length}">
<a class="test" tabindex="-1" href="#" #click=setSelectedItem(item.name,item.children.length,false)>{{item.name}}<span class="caret" v-if="item.children.length"></span></a>
<ul class="dropdown-menu" v-if="item.children.length">
<li v-for="child in item.children"><a tabindex="-1" href="#" #click="setSelectedItem(child.name,item.children.length,true)">{{child.name}}</a></li>
</ul>
</li>
</ul>
</div>
</div>
In Vue.js how do you target/detect the clicked element to perform a basic toggle class?
I've written this which toggles successfully but when you click an a the class is applied to to all li's
HTML
<ul id="app" class="projects">
<li v-bind:class="dyClass">Project A</li>
<li v-bind:class="dyClass">Project B</li>
<li v-bind:class="dyClass">Project C</li>
<li v-bind:class="dyClass">Project D</li> </ul>
JS
new Vue({
el: '#app',
data: {
show: false,
},
computed: {
dyClass: function() {
return {
show: this.show
}
}
}
})
I'm new to Vue.
EDIT.
I managed to get it working with a mix of help from below, but I dont seem to be able to get the toggle effect.
<ul id="app" class="projects">
<li :class="{show:selected == 1}">
<a href="" #click.prevent.stop="selected = 1" >Exposure</a>
</li>
<li :class="{show:selected == 2}">
<a href="" #click.prevent.stop="selected = 2" >Exposure</a>
</li>
<li :class="{show:selected == 3}">
<a href="" #click.prevent.stop="selected = 3" >Exposure</a>
</li>
</ul>
and
new Vue({
el: '#app',
data: {
selected: false,
}
});
You can pass element to function ($event):
:click=dyClass($event) Then in computed:
dyClass: function(event) {
event.target.toggleClass('whatever')
}
As i understand you have some li items and you want to add an active class when a specific li gets clicked.
Solution:
the "html" part:
<div id="app">
<ul class="projects">
<li v-for="project in projects"
:key="project.id"
:class="{ active: project.id === activeProjectId }"
#click="activeProjectId = project.id"
>
{{ project.name }}
</li>
</ul>
</div>
The "vue" part
new Vue({
el: "#app",
data: {
projects: [
{ id: 1, name: 'Project A' },
{ id: 2, name: 'Project B' },
{ id: 3, name: 'Project C' },
{ id: 4, name: 'Project D' },
],
activeProjectId: 1
},
})
Then add some css to the 'active' class.
For more, See the fiddle
I have a multi level dropdown menu working for Aurelia with bootstrap however whilst its three levels deep and uses as a basis THIS gist expanding on it I am having trouble adding a divider via the route settings.
Now a divider uses the class "divider" in the list tag <li></li> Ok so I thought by adding the entry divider: true in the settings for the dropdown I could check for that and instead if displaying the link etc I could instead show a divider however I dont know how to implement this into the navmenu.html file. Here is the file:
<ul class="nav navbar-nav">
<li repeat.for="route of router.navigation" class="${route.isActive ? 'active' : ''}">
<a href.bind="route.href" if.bind="!route.settings.nav"><span class="glyphicon glyphicon-${ route.settings.icon }"></span> ${route.title}</a>
<a href.bind="route.href" if.bind="route.settings.nav" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-${ route.settings.icon }"></span> ${route.title} <span class="caret"></span> <!--First level menu heading - requires route.settings.nav to exist-->
</a>
<ul if.bind="route.settings.nav" class="dropdown-menu">
<li repeat.for="menu of route.settings.nav" class="dropdown-submenu">
<a href.bind="menu.href" if.bind="!menu.navSettings.subNav"><span class="glyphicon glyphicon-${ menu.navSettings.icon }"></span> ${menu.title}</a>
<a href.bind="menu.href" if.bind="menu.navSettings.subNav" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-${ menu.navSettings.icon }"></span> ${menu.title} <span class="caret-right"></span>
</a>
<ul if.bind="menu.navSettings.subNav" class="dropdown-menu">
<li repeat.for="subMenu of menu.navSettings.subNav" class="dropdown-submenu">
<a href.bind="subMenu.href" if.bind="!subMenu.subNavSettings.subSubNav"><span class="glyphicon glyphicon-${ subMenu.subNavSettings.icon }"></span> ${subMenu.title}</a>
<a href.bind="subMenu.href" if.bind="subMenu.subNavSettings.subSubNav" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-${ subMenu.subNavSettings.icon }"></span> ${subMenu.title} <span class="caret-right"></span>
</a>
<ul if.bind="subMenu.subNavSettings.subSubNav" class="dropdown-menu">
<li repeat.for="lowestSubMenu of subMenu.subNavSettings.subSubNav" class="dropdown-submenu">
<a href.bind="lowestSubMenu.href"> <span class="glyphicon glyphicon-${ lowestSubMenu.subSubNavSettings.icon }"></span> ${lowestSubMenu.title}</a>
</li>
</ul>
</li>
</ul>
</li> [ALL THE ANCHORS HERE OR A DIVIDER.. HOW DO I DO A TERNARY TO CHECK ON EACH REPEAT FOR A DIVIDER VALUE IN THE SETTINGS ARRAY.
</ul>
</li>
</ul>
Here is an exert from the route map that the navmenu reads from:
{
route: "clients",
name: "clients",
moduleId: PLATFORM.moduleName("../components/clients/clientList/clientList"),
title: "Clients",
nav: true,
settings: {
nav: [
{
href: "#clients/clientsList",
title: "Client List",
navSettings: {
icon: "list",
roles: ["Employee", "Admin"],
}
},
{
navSettings: {
roles: ["Employee", "Admin"],
divider: true, // HERE IS MY DIVIDER
}
},
{
href: "#clients/Create",
title: "Create Client",
navSettings: {
icon: "user",
roles: ["Employee", "Admin"],
}
}
],
icon: "user",
auth: true,
roles: ["Employee", "Admin"],
pos: "left"
}
},
The problem is that the <li></li> does a repeat and I need to check in that repeat - li to see if "navSettings has an entry divider: true and if so not show the link (menu item) but instead show a line divider.
How do I discard the anchors and instead show a list line with class "divider". Whats throwing me is the fact that the li has a repeat.for and I need to either show everything between the <li></li>tags or instead show a divider.
I need to check on the line:
<li repeat.for="menu of route.settings.nav" class="dropdown-submenu">
and change the class from "dropdown-submenu" to "divider" while at the same time not show any of the anchors <a></a> by doing similar check (if.bind I am guessing) for divider..
Hope you can help..
In the <li> use class="${menu.divider ? 'divider' : 'dropdown-submenu'}".
Use if.bind on menu.divider for the elements inside the <li>.
<li repeat.for="menu of route.settings.nav" class="${menu.divider ? 'divider' : 'dropdown-submenu'}">
<a if.bind="!menu.divider" href.bind="lowestSubMenu.href"> <span class="glyphicon glyphicon-${ lowestSubMenu.subSubNavSettings.icon }"></span> ${lowestSubMenu.title}</a>
<div if.bind="menu.divider" class="divider"></div>
</li>
Twitter bootstrap has a dropdown menu option; where a menu has have multiple layers. See: http://getbootstrap.com/javascript/#dropdowns
How can I use Aurelia.js's routers to recreate this? Routers normally provide 1 level. I need 2 levels.
Credit for this goes to: https://github.com/adarshpastakia.
I "borrowed" most of this person's code to answer this question. You can find it at: https://gist.github.com/adarshpastakia/5d8462b5bc8d958d5cb3
Here are steps to answer the question above:
(1) In the router, add a "settings" property. It can be whatever you want. Here is an example:
settings:{
subMenu:[
{href:'#/sub1', title:'Submenu 1'},
{href:'zoldello.wordpress.com', title:'Submenu 2'},
{href:'#/sub3', title:'Submenu 3'}
]
}
Note: (a)It must be called "settings" (b) Aurelia currently ignores custom code you write outside "settings" (c)In "settings", you can place any property in it you like
(2) (a) From (1) above, if you need the submenu to route to a part of the page, in href (or whatever you call it) use "#sub1"; where "sub1" refers to a different route where nav is set to false.
(b) If you want a hyperlink independent of routing, set href (or whatever you call it) to the url you desire (I used "zoldello.wordpress.com" in my example). No need to add a additional route
(3) Follow the basic aurelia rules of building DOM (repeat, template etc)
Here is an example:
HTML file
<li repeat.for="route of router.navigation">
<!-- if route has no submenu -->
<a href.bind="route.href" if.bind="!route.settings.subMenu">${route.title}</a>
<!-- if route has submenu -->
<a href.bind="javascript:;" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false" if.bind="route.settings.subMenu">
${route.title} <span class="caret"></span></a>
<ul if.bind="route.settings.subMenu">
<li repeat.for="menu of route.settings.subMenu">
<a href.bind="menu.href">${menu.title}</a>
</li>
</ul>
</li>
Javascript file
configureRouter(config) {
config.map([{
route:'home',
title:'Home',
nav:true,
module:'home'
},{
route:'top-menu',
title:'Top Menu',
nav:true,
settings:{
subMenu:[
{href:'#/sub1', title:'Submenu 1'},
{href:'zoldello.wordpress.com', title:'Submenu 2'},
{href:'#/sub3', title:'Submenu 3'}
]
}
}, {
route:'sub1',
title:'Submenu 1',
nav:false,
moduleId:'module'
}, {
route:'sub2',
title:'Submenu 2',
nav:false,
moduleId:'module'
}, {
route:'sub3',
title:'Submenu 3',
nav:false,
moduleId:'module'
}])
}
small fix for Phil's answer
html:
<li class=" ${route.settings.subMenu ? '' : 'dropdown'} " repeat.for="route of router.navigation">
<!-- if route has no submenu -->
<a href.bind="route.href" if.bind="!route.settings.subMenu">${route.title}</a>
<!-- if route has submenu -->
<a href="#" class="dropdown-toggle" data-toggle="dropdown" if.bind="route.settings.subMenu">
${route.title} <span class="caret"></span>
</a>
<ul class="dropdown-menu" if.bind="route.settings.subMenu">
<li repeat.for="menu of route.settings.subMenu">
<a href.bind="menu.href">${menu.title}</a>
</li>
</ul>
</li>
js
configureRouter(config) { config.map([{
route:'home',
title:'Home',
nav:true,
moduleid:'home' },{
route:'top-menu',
title:'Top Menu',
nav:true,
moduleid:'module'
settings:{
subMenu:[
{href:'#/sub1', title:'Submenu 1'},
{href:'zoldello.wordpress.com', title:'Submenu 2'},
{href:'#/sub3', title:'Submenu 3'}
]
} }, {
route:'sub1',
title:'Submenu 1',
nav:false,
moduleId:'module' }, {
route:'sub2',
title:'Submenu 2',
nav:false,
moduleId:'module' }, {
route:'sub3',
title:'Submenu 3',
nav:false,
moduleId:'module' }])}
I was looking for the same thing when I landed here. The above answers where helpful but didn't take me as far as I needed to go. I learned of Bootstrap 3 dropdown sub menu missing and the work-arounds offered there but again needed something more.
Then I found http://www.smartmenus.org/ which provides the responsiveness and functionality I need in a drop-down menu for Aurelia for our production app. I worked with their team to get a version of the skeleton app that works well.
You can download it at http://www.smartmenus.org/files/demos/aurelia/SmartMenusDemo.zip.
The app.ts file is similar to the example above but adds support for font-awesome icons:
import {RouterConfiguration, Router} from 'aurelia-router';
import 'jquery';
import 'bootstrap';
import 'smartmenus';
import 'smartmenus-bootstrap';
export class App {
router: Router;
configureRouter(config: RouterConfiguration, router: Router) {
config.title = 'Aurelia';
config.map([
{ route: ['', 'welcome'], name: 'welcome', moduleId: './welcome', nav: true, title: 'Welcome' },
{
route: 'users', name: 'users', moduleId: './users', nav: true, title: 'Show Users',
settings: {
subMenu: [{ href: '#/users', title: 'Users', iconClass: 'fa fa-slideshare' },
{ href: '#/usersTest', title: 'Test Users', iconClass: 'fa fa-street-view' },
{
href: '#', title: 'Sub Sub', iconClass: 'fa fa-medium', settings: {
subMenu: [{ href: '#/child-router', title: 'Child Router', iconClass: 'fa fa-registered' },
{ href: '#/usersTest', title: 'Test Users', iconClass: 'fa fa-street-view' }]
}
},
{ href: '#/child-router', title: 'Child Router', iconClass: 'fa fa-registered' }]
}
},
{ route: 'usersTest', name: 'usersTest', moduleId: './usersTest', nav: false, title: 'Test Users' },
{ route: 'child-router', name: 'childRouter', moduleId: 'child-router', nav: false, title: 'Child Router' },
{ route: 'users', name: 'users', moduleId: './users', nav: true, title: 'Github Users' }
]);
this.router = router;
}
attached(): void {
$.SmartMenus.Bootstrap.init();
}
}
I implemented support for 4 levels of sub-menus in nav-bar.html:
<template bindable="router">
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#top-level-nav">
<span class="sr-only">Toggle Navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">
<i class="fa fa-home"></i>
<span>${router.title}</span>
</a>
</div>
<div class="collapse navbar-collapse" id="top-level-nav">
<ul id="main-menu" class="nav navbar-nav ">
<li repeat.for="route of router.navigation" class="${row.isActive ? 'active' : ''} ${route.settings.subMenu ? 'dropdown' : ''}">
<!-- if route has no submenu -->
<a href.bind="route.href" if.bind="!route.settings.subMenu">${route.title}</a>
<!-- if route has submenu -->
<a if.bind="route.settings.subMenu" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="true">
${route.title} <span class="caret"></span>
</a>
<ul if.bind="route.settings.subMenu" class="dropdown-menu">
<li repeat.for="l2SubMenu of route.settings.subMenu">
<a href.bind="l2SubMenu.href" if.bind="!l2SubMenu.settings.subMenu"><span class.bind="l2SubMenu.iconClass"> </span>  ${l2SubMenu.title}</a>
<a href.bind="l2SubMenu.href" if.bind="l2SubMenu.settings.subMenu" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="true">
<span class.bind="l2SubMenu.iconClass"> </span>  ${l2SubMenu.title} <span class="caret"></span>
</a>
<ul if.bind="l2SubMenu.settings.subMenu" class="dropdown-menu">
<li repeat.for="l3SubMenu of l2SubMenu.settings.subMenu">
<a href.bind="l3SubMenu.href" if.bind="!l3SubMenu.settings.subMenu"><span class.bind="l3SubMenu.iconClass"> </span>  ${l3SubMenu.title}</a>
<a href.bind="l3SubMenu.href" if.bind="l3SubMenu.settings.subMenu" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="true">
<span class.bind="l3SubMenu.iconClass"> </span>
  ${l3SubMenu.title} <span class="caret"></span>
</a>
<ul if.bind="l3SubMenu.settings.subMenu" class="dropdown-menu">
<li repeat.for="l4SubMenu of l3SubMenu.settings.subMenu">
<a href.bind="l4SubMenu.href"><span class.bind="l4SubMenu.iconClass"> </span>  ${l4SubMenu.title}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="loader" if.bind="router.isNavigating">
<i class="fa fa-spinner fa-spin fa-2x"></i>
</li>
</ul>
</div>
</nav>
</template>
As you can see, SmartMenus didn't require much change to the app but provides us with great responsive multi-level drop down menus in Aurelia with the power of Bootstrap regardless of Bootstrap depreciating support for that.
Hope this helps someone !
I have the following controller:
app.controller('MainController', ['$scope', function($scope) {
$scope.taskCategories = {
categories: [
'work',
'chores',
'learning'
]
};
$scope.tasklist = {
tasks: [{
title: 'Email Gregory',
category: 'work'
}, {
title: 'Clean the Kitchen',
category: 'chores'
}, {
title: 'AngularJS',
category: 'learning'
}, {
title: 'Hose Car',
category: 'chores'
}, {
title: 'Email Jethro',
category: 'work'
}
]
};
}]);
And am pulling the information through so far like this:
<div>
<li data-toggle="collapse" data-target="#work" class="nav_head workcat collapsed">
Work <span class="arrow"></span>
</li>
<ul class="sub-menu collapse" id="work">
<li ng-repeat="tasks in tasklist.tasks | orderBy:'title' | filter: {category: 'work'}">
{{ tasks.title }}
</li>
<li class="addwork">
<a href="">
<span class="fa-stack"> <i class="fa fa-2x fa-stack-2x fa-circle"></i><i class="fa fa-2x fa-stack-2x fa-plus-circle"></i>
</a>
</span>
</li>
</ul>
This would work fine doing a few times, one for each category, but I am looking to be able to add categories dynamically, and so I am looking for some way to go through the following steps:
So, I’ll need to loop all in categories.
During that loop, I’ll loop through the tasks and print out any task that matches the string of categories.index(1)
Then add 1 to category index and run again, till category.length runs out
I'm unfamiliar with looping inside a loop, and more unfamiliar again with doing it in angular. Anyone have any suggestions?
You could do an outer loop (ng-repeat) on the categories:
<ul class="sub-menu collapse" id="work" ng-repeat="cat in taskCategories.categories">
<li ng-repeat="tasks in tasklist.tasks | orderBy:'title' | filter: {category: cat}">
{{ tasks.title }}
</li>
<li class="addwork">
<a href="">
<span class="fa-stack"> <i class="fa fa-2x fa-stack-2x fa-circle"></i><i class="fa fa-2x fa-stack-2x fa-plus-circle"></i></span>
</a>
</li>
</ul>
Fiddle
Please refer below code snippet
angular.module('app',[]);
angular.module('app').controller('myController',function($scope){
$scope.taskCategories = {
categories: [
'work',
'chores',
'learning'
]
};
$scope.tasklist = {
tasks: [{
title: 'Email Gregory',
category: 'work'
}, {
title: 'Clean the Kitchen',
category: 'chores'
}, {
title: 'AngularJS',
category: 'learning'
}, {
title: 'Hose Car',
category: 'chores'
}, {
title: 'Email Jethro',
category: 'work'
}
]
};
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/js/bootstrap.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<body ng-app="app" ng-controller="myController">
<ul>
<li data-toggle="collapse" data-target=#{{c}} class="nav_head workcat" ng-repeat="c in taskCategories.categories">
<span class="arrow"> {{c}}</span>
<ul class="sub-menu collapse" id={{c}}>
<li ng-repeat="tasks in tasklist.tasks | orderBy:'title' | filter: {category: c}">
{{ tasks.title }}
</li>
</ul>
</li>
</ul>
</body>
Hope this helps!