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>
Related
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
I just started learning Vue because I want to move from PHP to Javascript.
I have a question that I can't solved and I hope you can help me with it.
I have a list of tasks. I want to update the status if I completed the task. If I click, the set as complete link, the task would move from the incomplete tasks to the list of completed tasks.
You can see on the screenshot, the Buy milk is in the completed tasks. What I am trying to do is to add a "completed" text or a check icon beside "Buy milk" on the All Task list.
Here is my code:
< script >
var app = new Vue({
el: '#root',
data: {
message: 'Hello world!',
tasks: [{
description: 'Go to the store',
completed: false
},
{
description: 'Buy milk',
completed: false
},
{
description: 'Feed the dog',
completed: false
},
{
description: 'Cook something',
completed: false
}
]
},
methods: {
setToCompleted() {
this.completed = true;
},
},
computed: {
incompleteTasks() {
return this.tasks.filter(task => !task.completed);
},
completedTasks() {
return this.tasks.filter(task => task.completed);
}
}
}); <
/script>
<div id="root">
<h3>All tasks</h3>
<ul>
<li v-for="task in tasks" v-text="task.description == true ? 'Completed' : 'Not completed'"></li>
</ul>
<h3>Incomplete Tasks</h3>
<ul>
<li v-for="task in incompleteTasks">{{ task.description }} | Set as completed</li>
</ul>
<h3>Completed Tasks</h3>
<ul>
<li v-for="task in completedTasks" v-text="task.description"></li>
</ul>
</div>
What I have tried Is I added a condition on a v-text directive. But it always show not completed. May you guide me why it is not changing? I would appreciate your help.
Thankyou.
EDIT======
This code solves my problem: thanks #tomrlh
<div id="root">
<h3>All tasks</h3>
<li v-for="task in tasks">
{{ task.description }} {{ task.completed ? 'completed' : '' }}
</li>
<h3>Incomplete Tasks</h3>
<ul>
<li v-for="task in incompleteTasks">{{ task.description }} | Set as completed</li>
</ul>
<h3>Completed Tasks</h3>
<ul>
<li v-for="task in completedTasks" v-text="task.description"></li>
</ul>
</div>
what about to check if the task is completed in your All Tasks exhibition, then showing conditionally the 'completed' message:
<h3>All tasks</h3>
<li v-for="task in tasks">
{{ task.description }} {{ task.completed ? ' | completed' }}
</li>
So let's say I've got this view and "Menu" is a collection of menu objects which may also have a collection of menu objects named Children as a property.
Here's the view -
<div class="collapse navbar-collapse navbar-right navbar-main-collapse">
<ul class="nav navbar-nav">
<li repeat.for="m of menu" class.bind="m.type=='child' ? 'dropdown' : ''" as-element="compose" data-type="${m.type}"
view="/client/landing/menubar/${m.type}menu"></li>
</ul>
</div>
And there are two views I'm using as my recursive menu, like so -
(View - no child collection)
<template>
<a href.bind="menu.link" data-info="${menu.type}">${menu.displayText}</a>
</template>
(View - with child collection)
<template>
${menu.displayText} <b class="caret"></b>
<ul class="dropdown-menu">
<li repeat.for="m of menu.children" data-info="${m.type}" class.bind="m.haschildren ? 'dropdown' : ''"
as-element="compose" view="/client/landing/menubar/${m.type}menu"></li>
</ul>
</template>
And the viewmodels for these two views both look like this -
import { customElement, bindable, inject } from "aurelia-framework";
#customElement("parentmenu")
export class ParentMenu {
#bindable menu;
}
I'm getting something. The views do display (although without recursion). The problem is that the repeat.for="m of menu" simply doesn't work below the bind in the first view.
Where have I gone wrong?
There's no need to use compose. Your menu could be a lot simpler, like:
<template bindable="model">
<ul>
<li repeat.for="item of model">
<a href.bind="item.link">${item.displayText}<a/>
<menu if.bind="item.children && item.children.length" model.bind="item.children"></menu>
</ul>
</template>
Usage:
<menu model.bind="menu"></menu>
JS:
menu = [
{
displayText: '1',
href: ''
},
{
displayText: '2',
children: [
{
displayText: '3',
href: ''
},
{
displayText: '4',
href: '',
children: [
{
displayText: '3',
href: ''
}
]
}
]
}
];
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.
I am working on a project with Mean JS and I am using the template offered by them at https://github.com/meanjs/mean .
Basically I want to do:
if (more than 1 sub-menus)
make it drop-down
else
make just a button and if that button clicked take it to state of the sub menu.
A button on the navigation bar will be defined as drop-down. It will have 2 sub-menus. This main button will be visible to all types of user. However, only 1 sub-menu on the drop down will be visible to general users. All 2 sub-menus will be visible to the admin users. I want to define it as drop down, but if there is only 1 sub-menu, don't show it as drop-down. When a user clicks on the main button it will take it to the page defined in the sub-menu.
Here is the code that is in the header.client.view.html (This is from the template, I have not change it.)
<nav class="collapse navbar-collapse" collapse="!isCollapsed" role="navigation">
<ul class="nav navbar-nav" ng-if="menu.shouldRender(authentication.user);">
<li ng-repeat="item in menu.items | orderBy: 'position'" ng-if="item.shouldRender(authentication.user);" ng-switch="item.type" ng-class="{ active: $state.includes(item.state), dropdown: item.type === 'dropdown' }" class="{{item.class}}" dropdown="item.type === 'dropdown'">
<a ng-switch-when="dropdown" class="dropdown-toggle" dropdown-toggle role="button">{{::item.title}} <span class="caret"></span></a>
<ul ng-switch-when="dropdown" class="dropdown-menu">
<li ng-repeat="subitem in item.items | orderBy: 'position'" ng-if="subitem.shouldRender(authentication.user);" ui-sref-active="active">
<a ui-sref="{{subitem.state}}" ng-bind="subitem.title"></a>
</li>
</ul>
<a ng-switch-default ui-sref="{{item.state}}" ng-bind="item.title"></a>
</li>
</ul>
</nav>
Here is what goes in the articles.client.config.js
// Configuring the Articles module
angular.module('articles').run(['Menus',
function(Menus) {
// Add the articles dropdown item
Menus.addMenuItem('topbar', {
title: 'Blog',
state: 'articles',
type: 'dropdown',
roles: ['*'],
position: 1
});
// Add the dropdown list item
Menus.addSubMenuItem('topbar', 'articles', {
title: 'Visit Blog',
state: 'articles.list',
roles: ['user', 'admin']
});
// Add the dropdown create item
Menus.addSubMenuItem('topbar', 'articles', {
title: 'Create Blog Post',
state: 'articles.create',
roles: ['admin']
});
}
]);