How to Close other accordian in angular js - angularjs

In the below code I am using toggle function which is working properly, but I want to close other accordingly, when one is open
<div class="listing_cat" ng-controller="categoryCtrl">
<ul>
<li class="mob_main_cat" ng-repeat="x in categories" ng-click="toggleCustom($index, $event)" >
<span class="cat_left"> {{x.category}}</span> <span class="cat_right"><i class="fa fa-plus"></i></span>
<div class="clearfix"></div>
<ul class="mob_sub_cat" ng-show="custom[$index]">
<li class="head">View all in Education</li>
<li ng-repeat="x in subcategories">{{x.subcategory}}</li>
</ul>
</li>
</ul>
</div>
<script>
$scope.custom = [];
$scope.toggleCustom = function(obj,event) {
event.stopPropagation();
$scope.custom[obj] = !$scope.custom[obj];
};
</script>
http://jsfiddle.net/U3pVM/16884/
Above is my jsfiddle link in which i want to close another when any one is clicked

Updated your fiddle with a solution, here:
http://jsfiddle.net/4m92fsqy/
Controller:
$scope.toggleCustom = function (obj, event) {
event.stopPropagation();
var temp = $scope.categories[obj].shown
for (var i=0; i < $scope.categories.length; i++) {
$scope.categories[i].shown = false;
}
$scope.categories[obj].shown = !temp;
};
HTML:
<ul class="mob_sub_cat" ng-show="categories[$index].shown">
Should be simple enough :)

Related

Display a long message in desired format using AngularJS

I have long message string. Each parent message is separated by a symbol # and child message separated by a symbol ^.
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
I want to display these messages in an unordered list format like below.
I used ng-repeat with ul-li to show the messages but the child messages are not properly aligned as nested ul-li elements and also show repeated messages.
<ul>
<li ng-repeat="message in messages.split('#')">
{{message}}
<ul>
<li ng-repeat="msg in message.split('^')">
{{msg}}
</li>
</ul>
</li>
</ul>
But this code doesn't show the desired output. My effort resides here.
Its better to convert the string into an object beforehand. I've tried to convert it into an object form so that it becomes easier for the template to read and conditionally show the parent-children relationship.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
$scope.messages = $scope.messages
.split("#").reduce((acc, item) => {
if (item.includes('^')) {
let c = item.split('^');
acc[c[0]] = c.slice(1, -1);
} else {
acc[item] = null;
}
return acc;
}, {});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="(key, value) in messages">
{{key}}
<ul ng-if="value">
<li ng-repeat="child in value track by $index">
{{child}}
</li>
</ul>
</li>
</ul>
</div>
You almost done it, check out some modifications:
angular.module('app', []).controller('MyCtrl', function($scope) {
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<ul ng-app='app' ng-controller="MyCtrl">
<li ng-repeat="message in messages.split('#')">
{{message.split('^')[0]}}
<ul>
<li ng-repeat="msg in message.split('^').splice(1)">
{{msg}}
</li>
</ul>
</li>
</ul>
I think this is what are you looking for
<li ng-repeat="message in messages">
{{message.text}}
<ul>
<li ng-if="message.sub" ng-repeat="msg in message.sub">
{{msg}}
</li>
</ul>
</li>
$scope.myFilter = function(input){
if(typeof input == 'string'){
var result = [];
var items = input.split('#');
for(var i=0;i<items.length;i++){
var item = items[i];
if(item.indexOf('^') == -1){//item doesn't have '^' means parent message
result.push({text:item});
}else{
//here my logic goes wrong to split child messages
var subItems = item.split('^');
//now If I push this subItems directly into result, not a good idea
result.push({sub: subItems.splice(1, subItems.length), text: subItems[0]});
}
}
return result;
}
return [];
};
https://jsfiddle.net/va94nqvd/12/

Angular JS - Nested JSON Driving a Two Level Navigation - How to Alter scope from directive?

I'm new to Angular but enjoying getting to know it! I'm having no problem populating data but I'm stuck on this navigational problem.
I have a sidebar divided into two navigation s. Both are reading from nested JSON of 'areas' and 'reports'. The idea is that the currently selected/clicked item in the left hand list will populate the elements in the right hand list, according to its children in the JSON.
I've got the initial population working fine. It reads the 'areas' and assigns the active area, which displays the reports. I then have a directive which applies css classes on the click event, but how can I get it to also alter the active area?
I'm currently doing scope.activeArea = scope.areas[1];, but this does not work. The index is just there for development; that will be replaced by the index of the clicked element.
My HTML:
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li ng-repeat="x in areas">
<a class="subnav-area-button" href="#" my-cool-directive>
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
And Javascript:
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
});
}] );
app.directive("myCoolDirective", function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$(elem).click(function() {
//var target = $(elem).next(".panel-collapse");
//target.hasClass("collapse") ? target.collapse("show") : target.collapse("hide");
$('.subnav-areas li').removeClass('active');
$(this).parent().addClass('active');
scope.activeArea = scope.areas[1];
});
}
}
});
Thanks!
Edit
Thanks to charlietfl's guidance my code now looks like this:
HTML
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li class="subnav-area" ng-repeat="x in areas">
<a class="subnav-area-button" href="#" ng-click="showReports($event, x.id)">
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
JS
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
$scope.showReports = function($event, index) {
$scope.activeArea = $scope.areas[index -1];
var theLi = angular.element($event.currentTarget).parent();
theLi.parent().find('li').removeClass('active');
theLi.addClass('active');
}
});
}] );
Edit 2
HTML
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li class="subnav-area" ng-repeat="x in areas" ng-class="{active: x==activeArea}">
<a class="subnav-area-button" href="#" ng-click="showReports($event, x)">
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
JS
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
$scope.showReports = function($event, item) {
$scope.activeArea = item;
}
});
}] );
Thanks again charlietfl!

$scope data is not updating in view for the first time

controller.js
$scope.getElectInfo=function(){
var selectedVal = $("#countriesList option:selected").val();
if (selectedVal != 0) {
$.get(APP_URL+ "/political/ElectionType/GetElectionTypesByCountry?countryId="
+ selectedVal,
function(data, status) {
$scope.data1=data;
console.log($scope.data1);
});
$scope.Structure = true;
}else
{
$scope.Structure = false;
}
}
html
<select id="countriesList" ng-change="getElectInfo()" ng-model="getElectionInfo">
</select>
<div ng-show="Structure" class="content">
<figure class="org-chart cf">
<ul class="administration">
<li>
<ul class="director">
<li>
<ul class="subdirector">
</ul>
<ul class="departments cf">
<li><a ><span ng-repeat="cname in country">{{cname.countryName}}</span></a></li>
<li class="department dep-b" ng-repeat="types in data1">
<a ><span>{{types.name}}</span></a>
</li>
In the above controller.js i am getting the country wise election types data,in the html page when i select the country for the first time $scope.data1 is not updating in view,select second time its updating can any one help me what is the problem!
finally i got it,
need to place $scope.$apply(); in function(data, status) { }

angularjs ng-show="true" but still has class="ng-hide"

I wanna see a div when I put the mouse over an image and remove it if I leave the mouse, with the ng-mouseenter and ng-mouseleave. But when I load my page, in the div appear class="ng-hide".
My code:
<nav class="navbar-default navbar-side" role="navigation" ng-app="panel" ng-controller="panelController">
<div class="sidebar-collapse">
<ul class="nav" id="main-menu">
<li class="text-center">
<img ng-mouseenter="inProfile()" ng-mouseleave="outProfile()" src="{{ asset('image/id1.jpg') }}" class="user-image img-responsive"/>
<div ng-show="panelController.evento">
Hi!!
</div>
</li>
<li>
<i class="fa fa-dashboard fa-3x"></i><span class="text-20">Dashboard</span></a>
</li>
<li>
<i class="fa fa-users fa-3x"></i><span class="text-20">Usuarios</span>
</li>
<li>
<i class="fa fa-lightbulb-o fa-3x padding-left-10"></i><span class="text-20 padding-left-10">Emprendedores</span></a>
</li>
<li>
<i class="fa fa-money fa-3x"></i><span class="text-20">Inversores</span></a>
</li>
<li>
<i class="fa fa-newspaper-o fa-3x"></i><span class="text-20">Noticias</span></a>
</li>
</ul>
</div>
</nav>
<script>
var tfc = angular.module('panel', []);
tfc.controller ( 'panelController' , [ '$scope' , function($scope){
$scope.inProfile = function(){
$scope.evento = "true";
}
$scope.outProfile = function(){
$scope.evento = "false";
}
}])
</script>
You problem is on page load eventto value is undefined that's why ng-show expression is hiding value on page load. you should define evento value to true to show it. You could this do from controller or also you could use ng-init="panelController.evento=true" on view
And make sure, you should use boolean rather than string which is used for expression evaluation in ng-show.
Code
var tfc = angular.module('panel', []);
tfc.controller('panelController', ['$scope', function($scope) {
$scope.inProfile = function() {
$scope.evento = true;
}
$scope.outProfile = function() {
$scope.evento = false;
}
//init values
$scope.evento = true;
}]);
Update
You should directly access value of scope variable on view as you are not using controllerAs in you application, it should be evento instead of panelController.evento
Markup
<div ng-show="evento">
Hi!!
</div>

Detect user selection for li

I have a list of items ("locals" array) which I show in a list
<ul class="list-group">
<li ng-repeat="loc in locals" class="list-group-item"><a href="" data-id={{loc.ID}}>{{loc.location}}</a>
</li>
</ul>
I want the user to be able to select an item, and then to use this item in code.
What is the preferred way to do it.
Also I am creating the application for mobile, so I should be able to know that the user chose this item in mobile( and not just use mouseclick for example).
You can make use of angular js ng-click event (on the li item where ng-repeat is and do something like this: fiddle
code snippet of controller:
function MyCtrl($scope) {
$scope.templateList = [{id:1, name: 'Template1'}, {id:2, name: 'Another Template'}]
$scope.template = {};
$scope.setValue = function(list) {
$scope.template.template_id = list.id;
$scope.template.template_name = list.name;
}
}
Of HTML:
<div ng-app>
<form ng-controller="MyCtrl">
<input type="hidden" name="template_id" ng-model="template.template_id" />
<input type="text" name="template_name" ng-model="template.template_name" />
<ul>
<li ng-repeat="list in templateList" ng-click="setValue(list)">{{list.name}}</li>
</ul>
</form>
</div>
Try this:
In html,
<ul class="list-group">
<li ng-repeat="loc in locals" class="list-group-item">
<a href="" data-id={{loc.ID}} ng-click="selectLoc(loc.location)">
{{loc.location}}
</a>
</li>
</ul>
In JS,
$scope.selectLoc = function(location){
console.log(location);
//Here you will get the selected location.
var SomeVar = location;
}
Hope this helps....

Resources