AngularJS: Controller loads only after page refresh - javascript

I am using AngularJS with ASP.NET MVC to create an application which uses Angular controllers for the front end.
When I run the application on my development system, it works fine. When I deploy it on my local IIS, it works fine. BUT, when I deploy it the to production server IIS, the angular controller does not load and it requires refreshing the page to get it to work.
I have looked at the similar questions, for instance:
Angular app only loads on page refresh
I also do not have any other extensions or plugins installed to affect the behavior as suggested in other similar questions.
I have moved all the JS in bundles, but that also to no avail. The order of the JS also seems to be correct because it works perfectly well on the development system, and local IIS.
I have no other idea on how to proceed with this issue.
Here's the screenshot for the error in the console:
And here's the code:
For HomeController,
app.controller('homeController', function ($scope, $uibModal, HomeService, RequestService) {
$scope.refreshOriginatorForms = function (searchCriteria) {
HomeService.getOriginatorRequestForms(searchCriteria).then(function (response) {
....
});
}
var originatorSearchCriteria = {
Pager: {
ItemsPerPage: 10,
CurrentPage: 1
}
};
$scope.OriginatorFormsSearchCriteria = originatorSearchCriteria;
$scope.initialize = function () {
$scope.refreshOriginatorForms($scope.OriginatorFormsSearchCriteria);
};
}
The $scope.initialize method is called in the view with ng-init="initialize()"

I have moved all the JS in bundles
If you are minimizing angular controllers then you should write our controller like this to that minimizers does not rename important angular keywords like $scope
app.controller('homeController',['$scope','$uibModal','HomeService','RequestService', function ($scope, $uibModal, HomeService, RequestService) {
$scope.refreshOriginatorForms = function (searchCriteria) {
HomeService.getOriginatorRequestForms(searchCriteria).then(function (response) {
....
});
}
var originatorSearchCriteria = {
Pager: {
ItemsPerPage: 10,
CurrentPage: 1
}
};
$scope.OriginatorFormsSearchCriteria = originatorSearchCriteria;
$scope.initialize = function () {
$scope.refreshOriginatorForms($scope.OriginatorFormsSearchCriteria);
};
}])

We finally got it solved. Our network engineer suggested enabling the CDN on the DNS, and it worked.
All this time, looking at the code, and the issue was something else.

Related

variable not found / undefined after grunt build (uglify)

I am using AngularJS for building a simple app with a map. As the main ctrl had too many logic I build a second controller for the navbar. Until here everything worked fine. Now I outsourced the map.on('zoomend' ... ) function when refactoring the main controller.
The problem now is, that when the navbar controller file is minified (through grunt build uglify) I get the following error:
Cannot read on of undefined
That means, map is undefined even though it is declared at the top of the file AND I do not have the problem on localhost (grunt serve).
Navbar Ctrl:
'use strict';
angular.module('angularMapApp').controller('navbarController', navbarController);
navbarController.$inject = ['$scope', '$mdSidenav', 'helper', 'RespondService', 'shipTypes'];
function navbarController($scope, $mdSidenav, helper, RespondService, shipTypes) {
var map = RespondService.getMap();
map.on('zoomend', function() {
timestamp = RespondService.getTimestamp();
selectedShipTypes = RespondService.getSelectedShipTypes();
selectedShipState = RespondService.getSelectedShipState();
showGrid = RespondService.getShowGrid();
helper.loadAndShowShipMarkers(timestamp, selectedShipTypes, selectedShipState, showGrid, map).then(function(results) {
$scope.numberOfShips = results;
RespondService.setNumberOfShips($scope.numberOfShips);
});
});
So this is a short version of my controller. The grunt file is still the same as created with yeoman. I too logged the map value at the top of the file, and there it has a value. However using 'map.on' might not work.
Maybe anyone can help me with that.
Your $inject seems to be correct, so minify should work fine for angular injection. It looks like var map is loading data from RespondService.getMap(). What do you expect to get from that function? You might want to put a break point and see if what you expecting is being returned.

Second call to angular.module causes routing to fail

I have an site I have put together based on a tutorial I found here
http://www.revillweb.com/tutorials/angularjs-in-30-minutes-angularjs-tutorial/
My app.js contains
angular.module('kolvir', ['ngRoute'])
.controller("kolvirController", function($http){
var vm = this;
vm.searchInput = '';
$http.jsonp (
'https://sfcons.azure-mobile.net/api/getcons/?
callback=JSON_CALLBACK')
.success(function (data){
vm.cons = data;
})
.error(function (data) {
console.log('ERROR');
});
});
I added a controller (gallery-controller.js )and routing appears to fail. After ripping things out I determined that adding the module call causes the failure, with:
angular.module('kolvir', ['ngRoute']);
Without it works just fine. I have a second site based on twitter bootstrap that uses the same pattern and it works just fine.
I am still new enough to angular I am not even certain what I should be searching for to find and answer, but so far I have not turned up anything similar to this.

Ionic loading indicator

Here a sample codepen to explain my needs.
Basically I'm running a 2-pages Ionic application.
Page 1 is nothing but an hyperlink to page 2.
Page 2 reads data from an external source and requires some time (2 seconds).
I'd like to show a loading indicator while page 2 is "loading" that inhibits every user action on that page. Is there any good patterns to achieve this goal? I can probably use scope variables such as showPage and angularJs ng-show or something like that, but I would avoid to copy this pattern in every page.
Any idea?
You can use angular-block-ui.
It is very simple to implement in your project. Once you've referenced the css:
<link rel="stylesheet" href="path-to-block-ui/angular-block-ui.min.css"/>
and the javascript:
<script src="path-to-block-ui/angular-block-ui.min.js"></script>
you can add the dependency to your module:
angular.module('myApp', ['blockUI'])
It uses interceptors for long http calls. You can see how it works in the Block on HTTP requests in the examples page.
In your situation things are slightly different cause there's no http request there (I know, it's a demo) so you have to force the ui block manually.
You can change the service injecting the dependecy to blockUI:
.factory('MyService', function($q, blockUI) { ... })
and call blockUI.start(); right before the long running process and blockUI.stop(); when the promise is resolved.
.factory('MyService', function($q, blockUI) {
var items = ['1', '2', '3', '4', '5'];
return {
all: function() {
var deferred = $q.defer();
blockUI.start();
setTimeout(function() {
deferred.resolve(items);
blockUI.stop();
}, 2000);
return deferred.promise;
}
}
})
See your modified sample here.
In one of my apps I've used another angular module called angular-loading-bar. I guess it is the most popular these days. This one works with interceptors as well but it doesn't block the UI.
The third option is to use the ionic $ionicLoading service.
You have to do a little bit of extra work here as this service only show a loading indicator and blocks the interface.
You can create an interceptor:
var app = angular.module('ionicApp', ['ionic'])
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function($rootScope) {
return {
request: function(config) {
$rootScope.$broadcast('loading:show')
return config
},
response: function(response) {
$rootScope.$broadcast('loading:hide')
return response
}
}
})
})
which listens to http requests and broadcasts an event loading:show.
When the server has responded with some data the interceptor broadcasts loading:hide.
Your app would intercept those events when the app runs:
app.run(function($rootScope, $ionicLoading) {
$rootScope.$on('loading:show', function() {
$ionicLoading.show({template: 'foo'})
})
$rootScope.$on('loading:hide', function() {
$ionicLoading.hide()
})
})
Answering my own question: $ionicLoading is what I was looking for.

Cordova file-transfer plugin download always yields http status 401 and error code 3

I'm using Ionic to build an app for Android, and when testing from a device, the call I make using the org.apache.cordova.file-transfer plugin always yields the same response.
Here's the code used to fire off the download:
$scope.getFile = function(){
var filePath = cordova.file.dataDirectory + "beer.json";
var uri = encodeURI('https://stormy-sierra-8448.herokuapp.com/api/?q=stones+pale+ale');
var options = {};
$cordovaFileTransfer.download(uri, filePath, options, true)
.then(function(result) {
$scope.status = result;
alert('success');
}, function(err) {
console.log(err);
}, function (progress) {
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
});
}
And then the response (from the console)
FileTransferError {
code: 3,
source: "https://stormy-sierra-8448.herokuapp.com/api/?q=stones+pale+ale",
target: "documents/beer.txt",
http_status: 401,
body: null…
}
body: nullcode: 3exception: nullhttp_status: 401source: "https://stormy-sierra-8448.herokuapp.com/api/?q=stones+pale+ale"
target: "documents/beer.txt"
__proto__: FileTransferError
My environment looks like this:
Cordova v5.0.0
Ionic 1.3.20
I've seen others post that downgrading the plugin made it work, but when I go below the current version I'm using (0.5), the app doesn't build. When I use the newest version (1.0), the app builds, but after it launches, the console says:
Uncaught module cordova-plugin-file.ProgressEvent not found - cordova.js:59
The device has a connection and verified with the 'device' plugin.
Please help!
In the end, I bootstrapped Angular to the device ready event in my main index.html file. Once the event fired, I didn't have to worry about plugins not being initialized and ready for use, which I think is one of the reasons the FileTransfer plugin was failing me.
Another thing I did was install and use the $iconic command for everything. Before, I was mixing $cordova [cmd] and $ionic [cmd]. Not sure that it really matters, but everything seems to be working properly now.
The bootstrapping logic is below. I personally think this is how every ionic project should be set up from the get-go. Just remember to remove the ng-app from your body tag or wherever you've placed it.
angular.element(document).ready(function() {
if (window.cordova) {
document.addEventListener('deviceready', function() {
angular.bootstrap(document.body, ['myApp']);
}, false);
} else {
angular.bootstrap(document.body, ['myApp']);
}
});
Still using the latest versions of Cordova and Ionic. :)

Angular Running Controller twice on browser reload

Problem:
I have an Angular app which works fine. It has 4 main page controllers which loaded inside the ng-view. All there controllers are connected to pages which routed via ngRoute.
When the app is loaded first time it works ok. But if I go to any of these pages and press browser's refresh(f5) the controllers are called twice. Is there any reason why they run once in the first instance and twice in a reload?
Common problem, you must have loaded your controller on ui-router and also in the HTML file. Just remove it from HTML file, always use router to inject controllers, its just good practice.
Sorry guys it was an issue with a promise with a return.
After login in I had following code
....
$scope.someMethod().then(function(_data){
...
if (something not related to _data) {
$route.reload();
} else {
$location.path("xcxcxcxcxcx");
}
...
})
in something method..
$scope.something = function(){
var deff = $q.defer();
....
APICALL.callAPI(xxxxx).then(function(data){
deff.resolve(data);
}, function(error) {
deff.reject();
});
return deff.promise;
};
The last return deff.promise returned the execution to the earlier method and ran $route..reload();
I am not 100% convinced but removing
return deff.promise;
solved the issue.

Categories

Resources