Ng-show not updating after value changed - angularjs

JS
$scope.getDiffs = function () {
return Module.getDiffs($scope.item.account_id, $scope.item.year)
.then(function (res) {
angular.forEach(res, function (v) {
angular.forEach($scope.months, function (m) {
if (m.month == v.month) {
m.diff = v.diff != 0;
}
});
});
});
};
Blade
<ul class="nav nav-tabs mbtm-10">
<li role="presentation" ng-repeat="m in months"
ng-class="{active: item.month == m.month}">
<a href="" ng-click="item.month = m.month;fetchTrx()">
#{{m.text}}
<i ng-show="m.diff != null" class="fa fa-circle"
ng-class="{'text-success': !m.diff, 'text-danger': m.diff}">
</i>
</a>
</li>
</ul>
My code will show the green circle on the taps interface if the value is m.diff != null. However, It will not updating if value is m.diff == null. Once the tap is show the green circle then it show forever green circle no matter in what value.

Use angular.copy:
$scope.getDiffs = function () {
return Module.getDiffs($scope.item.account_id, $scope.item.year)
.then(function (res) {
angular.forEach(res, function (v) {
angular.forEach($scope.months, function (m,i,arr) {
if (m.month == v.month) {
m.diff = v.diff != 0;
arr[i] = angular.copy(m);
}
});
});
});
};

Related

InfiniteScroll - AngularJS not working

Edit:
Just for checking purposes, I also did a console.log inside the nextPage function, to check if it's being triggered:
$scope.nextPage = function() {
var captureLength = $scope.captures.length;
console.log('TRIGGER');
if($scope.busy) {
return;
}
...
}
};
And it seems I'm getting a infinite loop, but I can't see why.
=================================
I'm trying to implement infinitescroll into a view but for some reason it's only loading the initial 4 images and not triggering the rest.
Here is my code:
CTRL:
/* ----------------------- Variables ----------------------- */
$scope.auth = auth;
$scope.captures = [];
$scope.following = [];
$scope.allData = [];
$scope.busy = true;
var page = 0;
var step = 4;
$scope.nextPage = function() {
var captureLength = $scope.captures.length;
if($scope.busy) {
return;
}
$scope.busy = true;
$scope.captures = $scope.captures.concat($scope.allData.splice(page * step, step));
page++;
$scope.busy = false;
if($scope.captures.length === 0) {
$scope.noMoreData = true;
}
};
/* ----------------------- Process Data ----------------------- */
$q.all({follows: findFollow(), users: getUsers(), captures: getAllCaptures()}).then(function(collections) {
var follows = collections.follows;
var users = collections.users;
var captures = collections.captures;
follows.filter(function(follow) {
return follow.follower_id === auth.profile.user_id;
}).forEach(function(follow) {
users.filter(function(user) {
return user.user_id === follow.followed_id;
}).forEach(function(user) {
$scope.following.push(user);
});
});
follows.filter(function(follow) {
return follow.follower_id === auth.profile.user_id;
}).forEach(function(follow) {
captures.filter(function(capture){
return follow.followed_id === capture.userId;
}).forEach(function(capture){
console.log(capture);
$scope.allData.push(capture);
});
});
$scope.nextPage();
$scope.busy = false;
});
/* ----------------------- Retrieve Services - Data ----------------------- */
function findFollow() {
return userApi.findFollow().then(function(res) {
return res.data;
});
}
function getUsers() {
return userApi.getUsers().then(function(res) {
return res.data.users;
});
}
function getAllCaptures() {
return captureApi.getAllCaptures().then(function(res) {
return res.data;
});
}
Partial:
<div class="col-md-8">
<div class="well main-well">
<h3 class="page-header-h3">Following Dashboard:</h3>
<hr />
<h4 align="center" ng-show="!captures.length">
<strong>The people that you are following, have not posted anything yet.. Yikes!</strong>
<br /><br />
Quickly, go follow more people!</h4>
<div class="row" infinite-scroll="nextPage()" infinite-scroll-disabled="busy || noMoreData" infinite-scroll-distance="0.1">
<ul class="dynamic-grid" angular-grid="captures" ag-id="gallery">
<li data-ng-repeat="capture in captures | orderBy :'created_at':true" class="grid">
<a ui-sref="detail({id: capture._id})">
<img ng-src="{{capture.picture}}" class="grid-img" />
<span class="follow-capture-info">
<span class="follow-capture-name"><span class="glyphicon glyphicon-user"></span>
{{capture.author}}
<span class="following-capture-time">·
<span class="glyphicon glyphicon-time"></span>
<span am-time-ago="capture.created_at"></span>
</span>
</span>
</span>
</a>
</li>
</ul>
</div>
<div ng-show="busy">Loading more...</div>
</div>
Anyone know where I went wrong?
Thanks.

What is the right syntax for ng-show with scope variable

I am setting a ng-show for when I have certain state so my delete button should be shown.
But it's not working. I checked in the console and my method is passing true to the scope variable. Still not sure what is wrong.
application.html
<ul class="nav navbar-nav navbar-right">
<li ng-show="notesState" ><a ng-really-message="Are you sure you want to delete this note?" ng-really-click="deleteNote(note)" class="glyphicon glyphicon-trash " style="float:left;" >Delete note</a></li>
<li><a href="#/home" >+ New Note</a></li>
<li ng-hide="signedIn">Login</li>
<li ng-show="signedIn">{{user.email}}</li>
<li class="pointer" ng-show="signedIn"><a ng-click="logout()">Logout</a></li>
</ul>
in notesCtrl.js
$scope.notesState = $state.is('notes')
is notesState true when the controller is loading? you might need to $scope.$apply() if it something that is false when the controller loads but becomes true later.
sometimes returning a function works but i really do not know why you would need to do this.
$scope.notesState = function(){ return $state.is('notes') }
ng-show="notesState()"
here is $state.is and the function it sometimes returns
$state.is = function is(stateOrName, params, options) {
options = extend({ relative: $state.$current }, options || {});
var state = findState(stateOrName, options.relative);
if (!isDefined(state)) { return undefined; }
if ($state.$current !== state) { return false; }
return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;
};
and
function equalForKeys(a, b, keys) {
if (!keys) {
keys = [];
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
}
for (var i=0; i<keys.length; i++) {
var k = keys[i];
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
}
return true;
}
if that helps anyone looking into this.
Try using this way.May be it works.
<li ng-show="notesState=='true'" >

ng-repeat pagination looses items

I'm learning AngularJS following the good Pro AngularJS written by Adam Freeman.
I'm stuck on ng-repeat pagination using filters. I know there are bootstrap ui directives for Angular, but i'm following this book in order to learn how angular works.
My code:
<section class="row-fluid" ng-controller="GetAjax">
<div class="col-md-12">
<h2>Repater Caricato in Ajax</h2>
</div>
<div class="row-fluid">
<div class="col-md-6" style="max-height: 350px; overflow-y: auto" ng-controller="PagedData">
<ul class="list-group">
<li class="list-group-item" ng-repeat="item in data.visitors | filter:query | range:selectedPage:pageSize">
<b>{{item.id}}.</b> {{item.first_name}} {{item.last_name}} | <small><i>{{item.email}} - {{item.country}} {{item.ip_address}}</i></small>
</li>
</ul>
<ul class="pagination">
<li ng-repeat="page in data.visitors | pageCount:pageSize"
ng-click="selectPage($index + 1)"
ng-class="pagerClass($index + 1)">
<a>{{$index + 1}}</a>
</li>
</ul>
</div>
</div>
</section>
Angular filters
angular.module("customFilters")
/******* Filters per la paginazione dei dati ******************/
//Genera il range di dati in base alla page size
.filter("range", function ($filter) {
return function (data, page, size) {
if (angular.isArray(data) && angular.isNumber(page) && angular.isNumber(size)) {
var start_index = (page - 1) * size;
console.log(data.length);
if (data.length < start_index) {
return [];
} else {
return $filter("limitTo")(data.splice(start_index), size);
}
} else {
return data;
}
}
})
//Calcola il numero di pagine
.filter("pageCount", function () {
return function (data, size) {
if (angular.isArray(data))
{
var result = [];
for (var i = 0; i < Math.ceil(data.length / size) ; i++) {
result.push(i);
}
return result;
}
else
{
return data;
}
}
});
Angular Controller
.controller("GetAjax", function($scope, $http){
$http.get('data/visitors.json').success(function(data) {
$scope.data = {visitors : data};
});
})
.constant("activeClass", "active")
.constant("perPage", 30)
.controller("PagedData", function($scope, $filter, activeClass, perPage){
$scope.selectedPage = 1;
$scope.pageSize = perPage;
console.log("page"+ $scope.selectedPage);
$scope.selectPage = function (newIndex) {
$scope.selectedPage = newIndex;
console.log( {idx: newIndex});
}
$scope.pagerClass = function (index) {
return (index == $scope.selectedPage) ? activeClass : "";
}
});
The result is that after 3 range filter invocations during the page render, the data array looses all the data.
Strange is that using the example from the book this code works perfectly.
Please, help me to know my error :D
splice function overwrites array
if you have an array
a = [1,2,3,4];
a.splice(2,1);
// a = [1,2,4]
results is a = [1,2,4]
use slice instead

AngularFire add in reverse order

I need to add objects to Firebase in reverse order. Or reverse data when goes data binding. Or sort objects by time of create.
var ref = new Firebase("https://[url].firebaseio.com/");
$scope.messages = $firebase(ref);
$scope.addMessage = function(e) {
$scope.messages.$add({title: $scope.title, body: $scope.msg, time: $scope.getDate() });
}
<div class="well span3 pull-left note" ng-repeat="(key, msg) in messages">
<button type='button' class='close' ng-click="messages.$remove(key)">×</button>
<b>{{msg.time| date: 'medium'}}</b>
<span>{{msg.title}}</span>
<span>{{msg.body}}</span>
<button ng-click="changeMessage(key)" class="btn btn-mini pull-right"><i class="icon-pencil"></i></button>
</div>
I try to use OrderBy atribute for ng-repeat but this is not easy because in messages are stored objects.
Check out the chat example in angularFire-seed. It uses a custom reverse filter
The reverse filter looks like so:
app.filter('reverse', function() {
function toArray(list) {
var k, out = [];
if( list ) {
if( angular.isArray(list) ) {
out = list;
}
else if( typeof(list) === 'object' ) {
for (k in list) {
if (list.hasOwnProperty(k)) { out.push(list[k]); }
}
}
}
return out;
}
return function(items) {
return toArray(items).slice().reverse();
};
});
And the usage is like so:
<ul id="messages" ng-show="messages">
<li ng-repeat="message in messages | reverse">{{message.text}}</li>
</ul>

i want hide only specific list element

i am new to angularjs. i have created list using ng-repeat. just i want to hide the selected list element from list:
html code which i prefered:
<ul>
<li ng-repeat="profile in profileMenu">
<div class="hederMenu" ng-hide="configureDisplay" ng-click="setProfile(profile.name)">
<a class="anchor" style="width:100%" >{{profile.name}}</a>
</div>
</li>
</ul>
here is controller code
$scope.profileMenu = [{
name : "My Profile"
}, {
name : "Configure"
}, {
name : "Logout"
}
];
$scope.profile = "";
$scope.setProfile = function (test) {
$scope.profileSelected = test;
if ($scope.profileSelected == "Configure") {
$location.path("/home/configure"); // if user click configure then this element will hide
$scope.configureDisplay = true;
}
if ($scope.profileSelected == "My Profile") {
$location.path("/home/dashboard");
$scope.configureDisplay = false;
}
if ($scope.profileSelected == "Logout") {
window.location.assign("http://mitesh.demoilab.pune/")
}
return $scope.profileSelected = test;
}
You have to set the configureDisplay property on the actual "Configure" profile item. Not sure what you're doing with the selection list, but I assume you would want the "Configure" item visible again when selecting another item. Therefore you'll also have to reset the "Configure" item back to false when selecting another item.
I modified your example a bit. Notice instead of passing the profile.name on setProfile, i'm passing the profile object. This just simplifies the interaction.
<ul>
<li ng-repeat="profile in profileMenu">
<div class="hederMenu" ng-hide="profile.configureDisplay" ng-click="setProfile(profile)">
<a class="anchor" style="width:100%" >{{profile.name}}</a>
</div>
</li>
</ul>
$scope.setProfile = function (selectedProfile) {
//reset the items
for (var i in $scope.profileMenu) {
$scope.profileMenu[i].configureDisplay = false;
}
if (selectedProfile.name == "Configure") {
$location.path("/home/configure"); // if user click configure then this element will hide
selectedProfile.configureDisplay = true;
}
if (selectedProfile.name == "My Profile") {
$location.path("/home/dashboard");
}
if (selectedProfile.name == "Logout") {
window.location.assign("http://mitesh.demoilab.pune/")
}
return true;
}
you need to do few changes ,
<li ng-repeat="profile in profileMenu">
<div class="hederMenu" ng-hide="profile.configureDisplay" ng-click="setProfile(profile)">
<a class="anchor" style="width:100%" >{{profile.name}}</a>
</div>
</li>
And in controler,
$scope.setProfile = function (test) {
$scope.profileSelected = test.name;
if ($scope.profileSelected == "Configure") {
$location.path("/home/configure");
test.configureDisplay = true;
}
if ($scope.profileSelected == "My Profile") {
$location.path("/home/dashboard");
test.configureDisplay = false;
}
if ($scope.profileSelected == "Logout") {
window.location.assign("http://mitesh.demoilab.pune/")
}
return test;
}

Resources