I have code that detects routing in controller Angular JS:
$scope.$on('$routeChangeSuccess', function() {
if($routeParams.user){
// AJAX
}
});
When I am on page with URL for this routing and do new AJAX request then the previous code is executed again. How to disable repeating executable?
Related
I am working on mobile app using:
Ionic 2.1.4
Cordova 6.4.0
Angular 1.5.3
I've one view with external url using InAppBrowser plugin and I have a link in this website should redirect to certain view in my app
this issue is $location.url() not redirecting and not working at all, but when I tested the event I found it trigger normally.
here is my full code
angular.module('yogipass').controller('iframe',function ($location) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log('here');
var ref=cordova.InAppBrowser.open('http://192.168.42.218/index.html', '_blank', 'location=no');
ref.addEventListener('loadstart', function(event) {
if (event.url.match("mobile/login")) {
console.log('worked!') // this logged normally
$location.url('/login');
ref.close();
}
});
}
])
You have to run digest cycle manually as you are changing location path from asynchronous event which is outside angular context.
Do wrap you code in $timeout function, which will fire up digest cycle. Apparently that will help to update location.
$timeout(function(){
$location.url('/login');
})
Right now I am using angular.element(document).ready(init()); but it calls init(); on every page refresh and not when browsing back and forth to the page. How could I call this function on every page view ?
I've tried also onload and ng-init and they don't work - the function doesn't get called.
I think this is what you're looking for:
$routeChangeSuccess Broadcasted after a route change has happened successfully. The resolve dependencies are now available in the
current.locals property.
ngView listens for the directive to instantiate the controller and
render the view.
This is what I do and it works for me:
$scope.$on('$routeChangeSuccess', function () {
// do something
});
Unless you're using ui-router. Then it's:
$scope.$on('$stateChangeSuccess', function () {
// do something
});
More info is found in the docs
in currently using angular-ui-router in my angularjs app. With main routes triggered from ui-sref directive in the top nav. How can I refresh a route even if I'm clicking on the current route.
Also if I'm in a subroute, then I want to refresh the view with the main route view.
Do I move this navigation into a custom function called upon ng-click?
So what I did was to create function within my controller:
$scope.navigateTo = function(stateName){
if($state.current.name == stateName){
$state.go($state.$current, null, { reload: true });
}else{
$state.go(stateName, {inherit:false});
}
}
this was then called from within my html via my ng-click directive:
ng-click="navigateTo('appname.resources')"
When switching Views in AngularJS (from #1 to #2), I am sending two XHR requests to the server. One of them is finished quicker and as soon as it is, the template gets rendered. However, in the template I'm referring to data that comes back from the second request, which at that time is not finished yet.
Is there a way that I can wait for all requests to finish before rendering the template?
Currently I'm simply defining methods in the controller and then at its bottom, executing the XHR requests and assigning the response to $scope variables.
If you're using the $compile directive to render your HTML-Templates dynamically, you could add
ng-show="showCtrl"
And in your controller preset
$scope.showCtrl = false;
If you have the standard route provider, wrap your HTML-Template with a DIV e.g.
<div style="display:none" or ng-show="showCtrl">
If your XHR Request is finished, just take the DIV-Element with attribute and say
display:block or
showCtrl = true; $scope.$apply();
Greetings
You should be using the promise service
Please refer to
https://docs.angularjs.org/api/ng/service/$q
I'd say the best way to handler this is to use a resolve on your router.
If you are using the default Angular router, see the docs here: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider, specifically the resolve property of the route definition. It allows you to specify any async calls that will be completed before the route changes and the next view is loaded.
If you use angular-ui-router, there is the exact same concept there.
Here is an example of using resolve from the angular docs:
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
});
});
Obviously they have a fake async call here with a timeout, but as long as your XHR call returns a promise (which will be the case if you use the $http service), then your controller can just be injected with delay in this case, and use the resolved data straight away.
I'm currently working on a project in angular. I'm trying to show a loading spinner every time the page changes. To accomplish this we are using ngRoute module and listening for routeChangeStart,routeChangeSuccess,routeChangeError events.
Here's the code:
$scope.$on('$routeChangeStart', function (event, param) {
var html = "<div class='panel-body'>"
+ "<div class='col-md-4 col-md-offset-4' style='top: 50%;'>"
+ "<i class='fa fa-spinner fa-spin'></i> Caricamento in corso..."
+ "</div>"
+ "</div>";
that.myModal = $modal.open({
template: html,
backdrop: 'static'
});
});
$scope.$on('$routeChangeSuccess', function (event, param) {
that.myModal.dismiss('nessuna');
});
$scope.$on('$routeChangeError', function (event, param) {
that.myModal.dismiss('nessuna');
});
This works, but only the first time a certain page is changed. I try to explain better: When we are in page X and navigate to page Y the modal is shown and then hidden after page changes. If then i go back to page X and navigate to page Y again the modal spinner is now shown.
When debugging I can see the modal.open() executing, but it's never shown. It looks like angular is somehow delaying the command.
Does anyone know why is this happening? Has anyone encountered this problem before?
About displaying the spinner solution capturing $http requests, here you have some info to get started:
http://lemoncode.net/2013/07/31/angularjs-found-great-solution-to-display-ajax-spinner-loading-widget/
Showing Spinner GIF during $http request in angular
The idea is to intercept a $http request and display the spinner, then on the end request or promise response (error and success) check if there are pending requests, if not hide the spinner.
If you need more info, give me a buzz, I have further developed this and taken some solutions for issues like I don't want to show the spinner for some particular requests.
Whatever solution you keep to catch route change events, I don't understood why your modal doesn't trigger.
Here is a demo in plunker (I used ui-bootstrap to handle modal).
You can use this nice script too called Pace to automatically start a loader based on http request.
Taken from their documentation:
Pace will automatically monitor your ajax requests, event loop lag, document ready state, and elements on your page to decide the progress. On ajax navigation it will begin again!