toggle show/hide of list items using angularjs - javascript

var myApp = angular
.module("myApp", [])
.controller("listController", function($scope) {
var foodList = [
{ name : 'Hyderbadi Koma',
types : [
{ name : "sweet" },
{ name : "extra chatpata" },
{ name : "chatpata" }
],
flag: 0
}]; ...
$scope.showhide = function(foodLists) {
if (foodLists.flag == 0)
foodLists.flag++;
else
foodLists.flag--;
};
});
...
<td class="leftSection">
<ul>
<li ng-repeat="foodItem in foodList" ng-click="showhide(foodItem)" class="clic">
{{ foodItem.name }}
<ul>
<li ng-repeat="foodType in foodItem.types" ng-hide="{{ foodItem.flag | filtering }}" class="unclic">
{{ foodType.name }} ///For watching variable flag {{foodItem.flag}}
</li>
</ul>
</li>
</ul>
...
Now here after tracing i found that "ng-click" is performing its action of changing the flag value from 1 to 0 and vice versa. Though I am not able to debug why ng-hide is not performing its action simultaneously, please help!

try this...
<td>
<ul ng-repeat="foodItem in foodList">
<li class="clic">
{{ foodItem.name }}
<ul ng-repeat="foodType in foodItem.types">
<li ng-hide="{{ foodItem.flag}}" class="unclic">
{{ foodType.name }}
</li>
</ul>
</li>
</ul>
</td>
https://plnkr.co/edit/sTWHI3SQeKgNN7QoOrrw

Related

Vue JS - How to do conditional display of text based on click event

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 }}&nbsp|&nbspSet 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 }}&nbsp|&nbspSet 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>

How to render the list in vue.js?

I'm trying to render the list with vue.js. The data has come from api call.
List rendering is ok, until I try to add data-feature_id="#{{searched_feature.id}}" in li tag.
When I add it, I got an error:
[Vue warn]: Error compiling template:......
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" data-feature_id="#{{searched_feature.id}}" #click="add_to_features_list">
#{{searched_feature.name}}
</li>
</ul>
</div>
How can I put searched_feature.id in data-feature_id attribute?
You need to add : before the attribute
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="searched_feature.id" #click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
if you wish to add the '#' in front of the data-feature_id attribute:
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="'#' + searched_feature.id" #click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
https://v2.vuejs.org/v2/guide/list.html coughcough*
var app = new Vue({
el: "#app",
data: {
searched_features: [
{
id: 1,
name: "One"
},
{
id: 2,
name: "Two"
},
{
id: 3,
name: "Three"
}
]
},
methods: {
add_to_features_list(){}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="searched_feature.id" #click="add_to_features_list">
#{{ searched_feature.name }}
</li>
</ul>
</div>
</div>
Add 'v-bind:' prefix of shorthand ':' before attribute to bind dynamic data.
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features"
:data-feature_id="searched_feature.id"
#click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
See more https://v2.vuejs.org/v2/api/#v-bind

"ng-class" on each clicked item

I need to add a class on selected <li> like I have shown in demo but dont want it to be removed if I click on another <li>.
Please help
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': model.selected==item}" ng-click="model.selected=item">{{ item.name }}</li>
</ul>
</div>
JS
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.model = {
selected: null,
items : [
{name: "Apple"},
{name: "Banana"},
{name: "California"}
]
};
})
demo
Just add like this
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': selected==$index}" ng-click="selected=$index">{{ item.name }}</li>
</ul>
</div>

Collapse nested ng-repeat created divs

I am trying to achieve something like the image below. This is my data:
JS:
angular.module('app', ['angular.filter'])
.controller('MainController', function($scope) {
$scope.showReport = {};
$scope.toggleShow = function (ym) {
$scope.showReport[ym] = !$scope.showReport[ym];
};
$scope.Reports = [
{ Id: 1, Name: 'Report One', Year: 2016, Month: 5 },
{ Id: 2, Name: 'Report Core', Year: 2016, Month: 5 },
{ Id: 3, Name: 'Report Alpha', Year: 2016, Month: 3 },
{ Id: 4, Name: 'Report Moon', Year: 2015, Month: 5 },
{ Id: 5, Name: 'Report Sky', Year: 2015, Month: 2 }
];
});
HTML:
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'">
{{ key }}
<ul ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<a ng-click="toggleShow(key+key1)"> O{{key1}} </a>
<li ng-repeat="p in value1" ng-if="!showReport[key+key1]">
{{p.Name }}
</li>
</ul>
</ul>
The objective is that if you click on any of the underlined numbers, the reports that belong to that month hide or show (collapsible). That's already done. This must also happen with the years- when you click a year, the months within must show/hide. I have tried many things but it seems I cannot figure it out what I need. I have made a JS BIN where my code is.
http://jsbin.com/huhabehoju/edit?html,js,output
Any help will be kindly appreciate it. Thanks
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
<meta name="description" content="[groupBy example]"/>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div ng-controller="MainController">
<ul ng-init= "yearhide=false" ng-repeat="(key, value) in Reports | groupBy: 'Year'">
<li ng-click="yearhide = !yearhide">{{ key }}</li>
<ul ng-hide="yearhide" ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<li ng-click="hideo = !hideo">O{{key1}}
<ul>
<li ng-show="hideo" ng-repeat="p in value1">
{{p.Name }}
</li>
</ul>
</li>
</ul>
</ul>
</div>
</body>
</html>
try this jsbin link,here is demo
I have created a jsbin for you here.
I have added a new function that will hide and show the months based on your years.
$scope.showYears = {};
$scope.toggleYear = function(year) {
if ($scope.showYears[year] === undefined || $scope.showYears[year] === null)
$scope.showYears[year] = false;
else $scope.showYears[year] = !$scope.showYears[year];
}
$scope.showMonth = function(month, year) {
if ($scope.showYears[year] === undefined || $scope.showYears[year] === null)
return true;
return $scope.showYears[year];
}
The HTML has been kept as
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'">
<div ng-click="toggleYear(key)">YEAR - {{ key }}</div>
<ul ng-repeat="(key1, value1) in value | groupBy: 'Month'" ng-show="showMonth(key1, key)">
<a ng-click="toggleShow(key+key1)"> MONTH - {{key1}} </a>
<li ng-repeat="p in value1" ng-if="!showReport[key+key1]">
{{p.Name }}
</li>
</ul>
</ul>
I cant see you toggleShow method, so I am assuming that you have already written the logic for that method.
can try this one no need to add any function in controller
<div>
<ul ng-repeat="(key, value) in Reports | groupBy: 'Year'" >
<span ng-click="hideGroup[key] = !hideGroup[key]" style="cursor:pointer;">{{ key }}- {{value.show}}</span>
<ul ng-hide="hideGroup[key]" ng-repeat="(key1, value1) in value | groupBy: 'Month'">
<span ng-click="hideGroup[key+key1] = !hideGroup[key+key1]" style="cursor:pointer;">O{{key1}}</span>
<li ng-hide="hideGroup[key+key1]" ng-repeat="p in value1">
{{p.Name }}
</li>
</ul>
</ul>
</div>
Updated:
orderBy works only for array so at first you need to convert it to array. and orderBy should be last filter and you need to add filter in your controller so inject $filter in your controller. can see this example
In Controller:
$scope.Reports= [];//your daata
$scope.showReport = {};
$scope.toggleShow = function (ym) {
$scope.showReport[ym] = !$scope.showReport[ym];
};
$scope.desc = function(arr) {
return $filter('min')
($filter('map')(arr, '-Year')); // descending by year
};
in Html:
<ul ng-repeat="reports in Reports | groupBy: 'Year' | toArray:true | orderBy:desc">
<li><span ng-click="toggleShow(reports[0].Year)" style="cursor:pointer">{{ reports[0].Year }}</span></li>
<ul ng-hide="showReport[reports[0].Year]" ng-repeat="items in reports | groupBy: 'Month'">
<li><span ng-click="toggleShow(reports[0].Year+items[0].Month)" style="cursor:pointer">O{{items[0].Month}} </span>
<ul ng-hide="showReport[reports[0].Year+items[0].Month]">
<li ng-repeat="item in items">
{{item.Name }}
</li>
</ul>
</li>
</ul>
</ul>
See Plunker Demo

How do I properly ng-repeat through nested key value pairs in angularJS

View live code:
Angular JS
How in the world do I properly loop through nested key value pairs and properly output them like below?
View I want is a tree like so
-touts
-classes
-col-12
-col-md-12
-col-lg-12
Currently the view is:
touts
{"classes":["col-12","col-md-12","col-lg-12"]}
JS:
var currentApp = angular.module('currentApp', []);
currentApp.controller('ACtrl', function($scope){
$scope.templates = {
'touts' : [
{
'classes' : ['col-12', 'col-md-12', 'col-lg-12' ]
}
]
};
});
HTML:
<div ng-app="currentApp">
<div ng-controller="ACtrl">
<ul ng-repeat="(key, prop) in templates">
<li>{{key}}</li>
<li>
<ul ng-repeat="class in templates[key]">
<li>{{class}}</li>
</ul>
</li>
</ul>
</div>
</div>
You are pretty close, I updated the fiddle. http://jsfiddle.net/y9wj6/9/
<ul ng-repeat="(key, prop) in templates">
<li>{{key}}</li>
<ul ng-repeat="val in prop">
<ul ng-repeat="(o, values) in val">
<li>{{o}}</li>
<ul ng-repeat="i in values">
<li>{{i}}</li>
</ul
</ul>
</ul>
</ul>
You must think gradually.
templates = {'touts' : [{'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }]};
// key = 'touts'
// props = [{'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }]
// props[0] = {'classes' : ['col-12', 'col-md-12', 'col-lg-12' ] }
// classkey = 'classes'
// classprop = ['col-12', 'col-md-12', 'col-lg-12' ]
// and print classprop by ng-repeat
So you can try this:
<div ng-app="currentApp">
<div ng-controller="ACtrl">
<ul ng-repeat="(key, props) in templates">
<li>{{key}}</li>
<li>
<ul ng-repeat="(classkey, classprop) in props">
<li>{{classkey}}</li>
<li>
<ul>
<li ng-repeat="class in classprop">
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
So this is pretty old question, however if you modified the object a bit (swap the array types for objects) the following template should work just fine.
angular.module('init', [])
.controller('test', ['$scope', function($scope) {
$scope.templates = {
'touts': {
'classes': {
'col-12': {},
'col-md-12': {},
'col-lg-12': {}
}
}
};
}]);
ul {
list-style: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="init" ng-controller="test">
<script type="text/ng-template" id="recursive_item.html">
{{key}}
<ul>
<li ng-repeat="(key, prop) in prop" ng-include="'recursive_item.html'"></li>
</ul>
</script>
<ul>
<li ng-repeat="(key, prop) in templates" ng-include="'recursive_item.html'"></li>
</ul>
</div>

Categories

Resources