AngularJS needs to execute a function two times to show the results - javascript

I have a navigation bar which has a drop-down menu item Log Out which calls the ngPostLogOut() function.
In app.js
.when("/logout", {
controller: 'AuthController',
templateUrl: "client/html/auth/logout.html"
});
AuthController
$scope.ngPOSTLogOut = function() {
if ($rootScope.user) {
$rootScope.user = null;
}
if ($window.sessionStorage) {
$window.sessionStorage.clear();
alert('Entered..');
}
alert('Before HTTP');
$http.post('server/auth/logout.php')
.then(function(result) {
$scope.logout = result.data;
});
alert('After HTTP');
/*
$timeout(function() {
$location.path('/');
}, 10000);
*/
};
logout.html
<div ng-controller="AuthController as auth">
<p ng-show='user == null' class="text-center">{{logout}}</p>
<br>
<button ng-click='ngPOSTLogOut()' class="btn btn-default btn-block">Angular To PHP</button>
Now, if a person clicks the Log Out item from the drop-down in the navbar then the function is called. I know this because I have set up alerts and they do pop up. But, the 'echo' from the login.php doesn't get featured. But, the odd thing is is that if I press the Angular to PHP button which also calls the ngPostLogOut() function, the function completes perfectly and as intended.
My guess
My guess is that ngRoute forces Angular to prioritize the HTML template switch making it so that the ngPOSTLogOut() function's parametres get ignored or dismissed.
The entire project on GitHub
https://github.com/AquaSolid/RAMA_Angular_PHP

Change this:
<li ng-click='ngPOSTLogOut()' ng-show='user != null'>Log Out</li>
to this:
<li ng-show="user != null"><a ng-click="ngPOSTLogOut()">Log Out</a></li>
And consider using ng-if rather than ng-show.

Related

AngularJS function in dialog called several times

Please see this code.
html code
<script type="application" id = "abc">
<md-dialog>
{{loadServerFile();}}
</md-dialog>
</script>
javascript code
loadServerFile : function(){
$.ajax({
url: "/homepage/create"
success: function(){
console.log("success");
$scope.closeDialog();
}
});
}
Here closeDialog close the id = 'abc' dialog.
But console.log("success") calling is doing more than 10 times.
Why this kind of problem happen?
How can I make this function call once?
javascript code
angular.module("imageedit").service('canvas',['$rootScope','$mdDialog'],function($rootScope, $mdDialog){
...
start: function(url){
$mdDialog.show({
template: $('abc').html()
controller: 'GGG'
clickOutsidetoClose: false,
})
...
}
...
})
Here I called $mdDialog.show to call dialog.
But in fact I only want to call loadServerfile in GGG controller.
Have you got any answer?
What I expect: $rootScope.call(loadServerFile);
Based on the new information, that you do not want the dialog, in your GGG controller, add this code, which will run one time. It will place the result of the call in $scope.homepageCreateResult. If you don't need to make this call at all, and do not need the dialog, delete all of the code you reference.
$scope.homepageCreateResult = {};
$http.get("/homepage/create")
.then(function(resp) {
console.log('success', resp);
$scope.homepageCreateResult = resp.data;
});
In your HTML, just remove all of this:
<script type="application" id = "abc">
<md-dialog>
{{loadServerFile();}}
</md-dialog>
</script>
In many of code, closeDialog function only hides dialog and not really close dialog.
And showDialog can be called lots of times.
You cannot see that but according to your question, console.log is called lots of times so my expection will be right.

Check when a list is fully rendered with angular

I have an ul that loads data from an array using a ng-repeat. The array is pretty big and the load of the list lasts too much.
I want to put a loader so its shown at the begining of the loading and hides just, and this is the important part, when that ul is fully rendered in the html.
My problem is that I can’t find a way to throw a function when the ul is fully rendered.
The way I have this right now is:
Controller:
function renderMatters() {
api_horus.getMatters()
.success(function (data)
{
$scope.matters = data.matters;
}
})
.error(function (error) {
status = 'Unable to load matters data: ' + error.message;
});
}
HTML:
<ul ng-model="matters" class="list clearfix" ng-class="{'floatingList':isHorizontal}">
<li ng-repeat="matter in filtered = (matters | filter:searchText) class="matter_grid_li">
…
I’ve tried these possible solutions already:
1. Using ngRoute and $viewContentLoaded:
In angular-directive.js
$scope.$on('$viewContentLoaded', function() {
App.initComponent();
alert("Loaded");
});
This works, but the alert is not thrown when the is fully loaded, but half way of it more or less.
2. Using a template, ng-include and onload
I put the ul in a different file and call it as a template
<div ng-include src="'template/test-loading.html'" onload="alert(‘ends’);"></div>
It does not work either. The alert shows at the middle of the load.
I even tried putting the ng-repeated li as the template instead of the ul because I read that the onload is thrown only when the PARENT element is loaded. Not success either.
How can I know when an element is fully rendered in HTML?
Tx in advance.
just create one div with
<div ng-if="showMsg">{{msg}}</div>
<div ng-if="!showmMsg">
<ul ng-model="matters" class="list clearfix" ng-class=" {'floatingList':isHorizontal}">
<li ng-repeat="matter in filtered = (matters | filter:searchText) class="matter_grid_li"></div>
In controller :
$scope.showMsg = true;
$scope.msg = "loading...";
function renderMatters() {
api_horus.getMatters()
.success(function (data)
{
$scope.matters = data.matters;
$scope.showMsg = false;
$timeout(angular.noop)
}
})
.error(function (error) {
status = 'Unable to load matters data: ' + error.message;
});
}

Refreshing page on a back button in angular/ionic

I am trying to refresh the page on the back button to get the new data for article list. To be more specific I have an article list, and the article page, on both of them I have an option of liking an article. When a user likes an article on the article page, if it hits the back button the like icon on the article list page won't get refreshed with the new state. I have tried with making a function on clicking the back button, and then getting the data again, but the icon doesn't change. The data that I get on console.log is new data and I get the value for like=1 which is correct if the user has liked the article, but the icon doesn't change.
This is my code:
I get the articles like this in my front page controller:
ArticleService.all().then(function(data){
$scope.articles = data;
})
In my article page html I have a back button link:
<a ng-click="refresh()"></a>
And in my article list I check which value I have for like and then show the icon according to that:
<a ng-if="article.like == 1" ng-click="like(article)" class="subdued">
<img class="social-images" src="icons/heart.svg"/> Lik
</a>
<a ng-if="article.like == 0" ng-click="like(article)" class="subdued">
<img class="social-images" src="icons/heart-outline.svg"/> Lik
</a>
This is my function in the article controller:
$scope.refresh = function (){
return $state.go('main.front').then(function(state) {
ArticleService.all().then(function(data){
$scope.articles = data;
console.log(data);
})
})
};
But since that function is in the article controller it cannot refresh the data on the front page. How can I refresh the data in the front page controller from the page that has a different controller?
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
try adding cache : false in your state to reload the state on enter ...
Try one of these:
1.
$scope.$on('$ionicView.beforeEnter', function () {
$scope.refresh();
});
$scope.refresh = function (){
return $state.go('main.front').then(function(state) {
ArticleService.all().then(function(data){
$scope.articles = data;
console.log(data);
})
})
};
2.
$scope.$on('$tateChangeSuccess', function () {
$scope.refresh();
});
It may be cache issue. So add,
<ion-view cache-view="false" view-title="My Title!">
</ion-view>

AngularJS : Removing rootScope listener doesn't work

I've got the following code in a controller :
var deregisterSetPermissions = $rootScope.$on("setPermissions", function () {
[... some code used when the user click on a "create account" button...]
});
$scope.$on('$destroy', function() {
deregisterSetPermissions;
[... and other listeners are unregistered ...]
}
When I leave the page, all the listeners are unregistered : I can see through the chrome developer console that $rootScope.$$listeners.setPermissions[] contains a single value, which is null.
When I come back to the page and after it loaded, $rootScope.$$listeners.setPermissions[0] contains null and $rootScope.$$listeners.setPermissions[1] contains the function the listener will have to call.
$rootScope.$$listenerCount.setPermissions is 1.
But when I click on the "create account" button, the function used by the "setPermissions" listener is called twice !
How can it be ?
Here's what I tried :
1- Checked that there are no other listeners created with the name "setPermissions"
2- Delete the content of the listener when the scope is destroyed :
$scope.$on('$destroy', function() {
$rootScope.$$listeners.setPermissions=[];
$rootScope.$$listenerCount.setPermissions = 0;
});
But still after that, if I leave the page and come back 3 times, a click on the "create account" button will cause the "setPermissions"-listener-function to be called 3 times...
It would be nice to understand why the listener's function is called more than once; and if you have a solution or an idea to help me going on, I am looking forward to reading it !
deregisterSetPermissions is a function. To unsubscribe the listener, you have to call it.
$scope.$on('$destroy', function() {
deregisterSetPermissions();
}
Generally, any time you find yourself using a function object that begins with the double dollar signs ($$) in Angular, it means you're doing something wrong - that's Angular's naming convention for something that isn't part of their public API!
I found some useful information from this question:
how to unsubscribe to a broadcast event
Which I used to construct an example:
var app = angular.module('app', [])
.controller('AppController', function($rootScope) {
var appCtrl = this;
$rootScope.manageNumbers = false;
appCtrl.addNumber = function() {
$rootScope.$broadcast('addNumber');
};
})
.controller('NumbersController', function($rootScope, $scope) {
var numCtrl = this;
numCtrl.numbers = [];
numCtrl.number = 0;
// Register and set handle
console.log('Register listener');
var registerListener = $rootScope.$on('addNumber', addNumber);
logListenerData();
// Unregister
$scope.$on('$destroy', function() {
console.log('Unregister listener');
registerListener();
// $rootScope.$$listeners.addNumber.length = 0;
logListenerData();
});
function addNumber() {
numCtrl.numbers.push(numCtrl.number);
numCtrl.number++;
}
function logListenerData() {
console.log('$rootScope.$$listeners');
console.log($rootScope.$$listeners);
console.log('$rootScope.$$listenerCount');
console.log($rootScope.$$listenerCount);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="AppController as appCtrl">
<button ng-click="$root.manageNumbers=true;" ng-if="!$root.manageNumbers">
Start Number Management
</button>
<button ng-click="$root.manageNumbers=false;" ng-if="$root.manageNumbers">
Stop Number Management
</button>
<button ng-click="appCtrl.addNumber()">
Add Number
</button>
</div>
<div ng-controller="NumbersController as numCtrl" ng-if="$root.manageNumbers">
<p>
<b>Numbers:</b>
<span ng-repeat="number in numCtrl.numbers">
{{ $last ? number : number + ', ' }}
</span>
</p>
</div>
</body>
Notice a few things. Even when you unregister an event, unless that event was triggered while it was registered, it will have a "ghost" null value in the $$listeners but will not show up in the $$listenerCounts. With the commented out line that sets the length to 0 I was able to remove these ghosts, however; it causes no actual difference as far as I can tell.
I finally found the root of the problem.
There was an other rootScope-listener in a service which wasn't destroyed, which is emitting the "setPermissions" message. Thus, I could try all I wanted, but I was looking at the wrong place..

Delayed search using Angular

I am working with a search control for one of my project using Angular. I was trying for delayed response like the search box should wait until 2 seconds before calling the relevant function.
When I search the web, most of the suggestion was to use a directive. I cannot use directive since clicking the search result in turn shows another set of results. I got another solution after pondering over in the web.
My code:
<div ng-controller="ReportCtrl" ng-app="pReport">
<input type="text" ng-model="searchString" placeholder="Search"/>
<div ng-show="display == 'search'">
<ul>
<li ng-repeat="i in batches">
<a ng-click='selectBatch(i.batchnumber)'>{{i.batchnumber}}</a>
</li>
</ul>
</div>
<div ng-show="display == 'repdetail'">
<ul>
<li ng-repeat="i in reports">
<a href='{{i.filename}}'>{{i.screenname}}</a>
</li>
</ul>
</div>
</div>
Angular Expressions
var app = angular.module('pReport', []);
app.controller('ReportCtrl', function ($scope, $http, $timeout) {
var timer = false;
$scope.batches = [];
$scope.reports = [];
$scope.$watch('searchString', function () {
if (timer) {
$timeout.cancel(timer);
}
timer = $timeout(function () {
$http({ }). //POSTING DETAILS
success(function (data, status, headers, config) {}); //SEARCH RESULTS
}, 1000)
});
$scope.selectBatch = function (batchNumber) { } // SEARCH FURTHER
});
Is there anything wrong in this approach of delaying?
Should I use a directive?
Is there any other most efficient approach?
Thanks in advance for your help!
What you're looking for is a debounce. Lodash provide this capability out of the box. The good news is Angular is getting this functionality in an upcoming version built-in.
It prevent execution of a function more than once per given time period. This is ideal for situations like a typeahead search box where you'd like to wait before firing off another request to the server and event handling in general.
In this case, I'd remove the watch and the move the $http call to its own function wrapped in a debounce:
$scope.search = function() {
_.debounce($http(...), 1000, { leading: false, trailing: true })
}
The leading and trailing just configure when the debounce will occur, in our case, we want it to happen after the initial 1000 wait.
And then change the input box to use ng-change so it triggers the function when a user types in something, but only once every 1000ms:
<input type="text" ng-model="searchString" placeholder="Search" ng-change="search()"/>

Categories