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

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) { }

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!

all arrays are not showing with angular

This is my controller that will fetch all notes for my main page. When I console.log($scope.allNotes) all my arrays are logged but when I render with my HTML only 1 array shows up
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
var data = result.data
data.filter(function (notes) {
$scope.allnotes = notes.notes
console.log($scope.allnotes)
})
})
}
my HTML:
<section class="row all-notes">
<h1>All Notes</h1>
<div class="allNotes">
<ul ng-repeat="notes in allnotes">
<li>{{ notes }}</li>
</ul>
</div>
</section>
<a class="btn btn-default" href="#/login">Login</a>
I solved it in a very hacky way.
Heres my new controller
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
$scope.allnotes = result.data
})
}
my HTML, this is where the magic happens. lol
<ul ng-repeat="notes in allnotes track by $index">
<li>{{ notes.notes.toString() }}</li> // i had no idea I can use toString() here
</ul>

How to Close other accordian in angular js

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 :)

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>

Resources