Why routing does not accept normal conditional checking code in angularjs - angularjs

I wanted to check some conditioning before the page loads, So I used resolve property
as
when('/home', { templateUrl: 'views/home.html', controller: 'homeController',resolve: {
user: function () {
if (localStorage.getItem('FBUserData') === null) {
$location.url('/login');
}
}()
}}).
But this did not work, as it was showing the error like:
Error: [ng:areq] Argument 'fn' is not a function, got undefined
'
So I moved the function to controller and tried calling from there, but this gave different error:
Modified code
var angAuth = angular.module('angularAuthApp'[...]);
angAuth.config(function ($routeProvider, $locationProvider) {
$routeProvider.
when('/home', { templateUrl: 'views/home.html', controller: 'homeController',resolve:homeController.checkUserFBSession})
....
....
});
And in homeController:
angAuth.controller('homeController', function ($scope, $location) {
$scope.checkUserFBSession = function(){
if(localStorage.getItem('FBUserData') === null){
$location.url('/login');
}
};
...
});
Here after adding resolve:homeController.checkUserFBSession, I am getting the error like
Failed to instantiate module angularAuthApp due to: homeController is not defined

The reason is that resolve's value is "an optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated."
This means that user needs to be evaluated before the controller is instantiated. Therefore you can't use a function defined in the controller to evaluate user.
You first approach should work thought (if properly implemented).
resolve is a key-value map, where key is the name of the dependency injected into the controller and value is either a string (denoting the name of a service) or a function. The function is called by Angular, but in your case you are calling it yourself and return undefined, so Angular sees undefined where it expects a function or a string.
You should change this:
user: function () {...}()
to that:
user: function ($location) {...}
Note: In order to use $location you also need to inject it into the function.
See, also, this short demo.

Related

Angular route resolve not passing to controller

For some reason whatever i do i cannot get my data to the controller no matter what i do, i keep getting this error
Error: [$injector:unpr] Unknown provider: initDataProvider <- initData <- PackingScanController
first file
var Application = angular.module('ReporterApplication', ['ngRoute']);
Application.config(['$routeProvider', '$interpolateProvider',
function($routeProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$routeProvider
.when('/packing/scan.html', {
controller: 'PackingScanController',
templateUrl: 'packing/scan.html',
resolve: {
initData : function () {
return "shite";
}
}
}) etc more code
second file
Application.controller('PackingScanController', ['$scope', '$http', 'initData', function($scope, $http, initData) {
var packer = this;
$scope.packedToday = initData;
The posted code is all right, you are injecting initData properly with resolve route block. However you are probably using explicit ngController in you route template. You don't want it, and of course in this case there is no initData service available which results in error you are getting.
Solution is simple: just remove
ng-controller="PackingScanController"
from your packing/scan.html template and it will work fine.
Explicit controller binding is not needed in this case since template is already bound properly to controller instance created behind the scene by $route service, with all necessary dependencies properly injected.

$state, $stateParams, getting undefined object

I am getting unexpected results from both methods.
I have my $state configed
$stateProvider
.state('status', {
url: "/status/:payment",
controller: 'QuestCtrl',
templateUrl: "index.html"
});
And on the Controller I have:
angular.module('quest').controller('QuestCtrl',function($scope,$stateParams,$state){
console.log($stateParams.payment); // undefined
console.log($state); // Object {params: Object, current: Object, $current: extend, transition: null}
}
I already used $stateParams in other projects and it worked but now I can't figure out what is going on here..
['$scope','$stateParams','$state',
function($scope, $http, $stateParams, $state)
The names of the services don't match with the variables.
So $http is actually the $stateParams service, $stateParams is actually the $state service, and $state is undefined.
My advice: stop using this array notation, which clutters the code and is a frequent source of bugs. Instead, use ng-annotate as part of the build procedure, which will do it, correctly, for you.
As I already commented above You forgot to inject $http service
angular.module('quest').controller('QuestCtrl',
['$scope','$http','$stateParams','$state',function($scope,$http,$stateParams,$state){
console.log($stateParams); // Empty Object
console.log($stateParams.payment); // Empty Object
console.log($state); // I get the entire state, I can see that my params are there.
console.log($state.params);
}
So your parameters mismatch and it turns out you will get $state in $stateparms and $state is empty.
And $http hold $state :P
Hope it helps :)
With the ng-annotate library, the controller can be also initiated like this:
angular.module('quest')
.controller('QuestCtrl', function ($scope,$http,$stateParams,$state) {
});
In this case you are avoiding problems with the injected objects ordering. Look at: https://github.com/olov/ng-annotate
If you are building your application with Grunt, use: grunt-ng-annotate package.
Missing parameter in routes.js
My example:
.state('menu.cadastroDisplay', {
url: '/page9',
views: {
'side-menu21': {
templateUrl: 'templates/cadastroDisplay.html',
controller: 'cadastroDisplayCtrl'
}
},
params: { 'display': {} }
})
Without this params in routes the $stateParams.yourParam always returns undefined.
Call 'ngInject'
constructor($scope, $reactive, $stateParams, $state, $sce) {
'ngInject'

routeprovider using resolve to pass value to controller

I'm looking for a way to pass a value to my controller from my appRoutes. With the idea for it to call a function and do some magic. heres some code so you get an idea:
appRoutes.js
$routeProvider
.when('/students/some/path/:id', {
templateUrl: 'views/studentRecord.html',
controller: 'StudentsController',
resolve: { myVar: 'test' }
});
studentsCtrl.js
angular.module('StudentsCtrl', [])
.controller('StudentsController', function($scope, $http, $routeParams,
$location, myVar, Students) {
/* ... */
});
Ideally, I'd like to call a given function within this controller - but parsing a value would be just as good. The idea is that the controller handles all pages to do with 'students' and will make some http calls so my node server will do some calls to mongodb. Ive tried a few variations on the internet and with no luck. I got an error:
Error: $injector:unpr Unknown Provider
but I'm not sure how to resolve it.
EDIT: I've half resolved this now by using this; http://plnkr.co/edit/mSb58e8cGDNYU27xSizk?p=preview
ideally i'd like to separate the app.js into controllers and services - currently working on this, any edit of the plnkr would be great.
Question still stands of is it possible to hit a function within the controller first, rather than resolving one through a service?
In each resolve property, you can have a function that lets Angular inject services for you to use:
resolve: {
myVar1: function(testService) { return testService.fetchList1(); },
myVar2: function(anotherService, $http) {
// call service functions to mongo-db or what have you
return result;
}
}
Then, your controller, just inject the properties:
// myVar1 and myVar2 are now here
app.controller('StudentsController', function($scope, myVar1, myVar2) {
/* ... */
});
If the returned value from the function inside resolve is a promise, then it will be resolved before controller code is called (hence, the name resolve). This is actually the recommended approach as it makes service code (such as testService) reusable across many controllers.
Passing a function that returns the value
.state('tab2', {
url: '/tab2',
templateUrl: 'templates/tab2.html',
controller: 'Tab2Controller as tab2Ctrl',
//promise
resolve: {
lastName: function () { return 'makarov'}
}
});
Then in the controller
function Tab2Controller(lastName) {
console.log("Tab2", lastName);
}

angularjs [ng:areq] Argument 'fn' is not a function, got string

I am new to angular js..I am getting follwing error please help me out
[ng:areq] Argument 'fn' is not a function, got string
var app = angular.module('demo',[]);
app.config('$routeProvider',function($routeProvider){
$routeProvider.when('/add',{
templateUrl:'demo/add.html',
controller:'addcontroller'
}).
when('/order',{
templateUrl:'demo/order.html',
controller:'ordercontroller'
});
});
app.controller('addcontroller',function($scope){
$scope.message="order";
});
app.controller('ordercontroller',function($scope){
$scope.message="order";
});
I think the error is in the config block, it should either be:
app.config(function($routeProvider){
// routeProvider config
});
or better:
app.config(['$routeProvider', function($routeProvider){
// routeProvider config, allows minification
}]);
the annotations are there for minification to work correctly. You can read more about it on AngularJS docs https://docs.angularjs.org/tutorial/step_05
Please note that this practice needs to be done throughout the app to work correctly.
Although not directly related to the context of this question, this error message can also be caused by a resolve block returning something else than a function, like this:
$stateProvider.state('mystate', {
url: "/myurl",
templateUrl: "mytemplate.html",
controller: "MyController",
resolve: {
authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser
}
});
if securityAuthorizationProvider.requireAuthenticatedUser happens to be undefined, you can get this error.
I know this is an older post, but thought I'd contribute what was wrong with my code with this exact error. I was injecting a service into my controller this way:
theApp.directive('theDirective', 'myService', ['$http', function ($http, myService) {}]);
Instead of this:
theApp.directive('theDirective', ['$http', 'myService', function ($http, myService) {}]);
Notice that my service was included outside of the inline array annotation! It was a boneheaded move on my part that cost me way too much time.
For the the problem was defining factory dependency outside the array. Most probably the minification was also an issue.
//Error in this
angular
.module('mymodule').factory('myFactory', 'thisconstant', function (thisconstant) {
});
This fixed by
//correct code
angular
.module('mymodule').factory('myFactory', ['thisconstant', function (thisconstant) {
}]);
Since there's been various use cases added here, I thought I'd also add mine. I got this error when re-formating a function service
angular
.app('myApp')
.service('MyService', function (){
// do something
return MyService;
})
into a class object:
export default class MyService { ... }
angular
.app('myApp')
.service('MyService', MyService);
My problem was that my service was returning itself at the end of the function and I needed to add a class function, which would do this:
export default class MyService {
constructor(){
// doing something
}
get() {
return MyService;
}
}
which fixed the issue for me. :)
I got this error by misunderstanding the way anonymous functions and named functions are treated in JavaScript.
This causes the error:
angular.module("app").factory("myDataService", ['$resource', myDataService]);
var myDataService = function($resource) {
return $resource('/url');
}
I should've either done this:
var myDataService = function($resource) {
return $resource('/url');
}
angular.module("app").factory("myDataService", ['$resource', myDataService]);
Or this:
angular.module("app").factory("myDataService", ['$resource', myDataService]);
function myDataService($resource) {
return $resource('/url');
}
More on the difference between anonymous function and named function here
In First line you need to use like this,
var app = angular.module('demo', ['ngRoute']);
and use the routing thing like this,
$routeProvider.when('/add').then({
templateUrl:'demo/add.html',
controller:'addcontroller'
});
Just try these steps once.

AngularJS Dynamic loading a controller

I read a lot about lazzy loading, but I am facing a problem when using $routeProvider.
My goal is to load a javascript file which contains a controller and add a route to this controller which has been loaded previously.
Content of my javascript file to load
angular.module('demoApp.modules').controller('MouseTestCtrlA', ['$scope', function ($scope) {
console.log("MouseTestCtrlA");
$scope.name = "MouseTestCtrlA";
}]);
This file is not included when angular bootstap is called. It means, I have to load the file and create a route to this controller.
First, I started writing a resolve function which has to load the Javascript file. But declaring my controller parameter in route declaration gave me an error :
'MouseTestCtrlA' is not a function, got undefined
Here is the call I am trying to set :
demoApp.routeProvider.when(module.action, {templateUrl: module.template, controller: module.controller, resolve : {deps: function() /*load JS file*/} });
From what I read, the controller parameter should be a registered controller
controller – {(string|function()=} – Controller fn that should be associated with newly created scope or the name of a registered controller if passed as a string.
So I write a factory which should be able to load my file and then (promise style!) I whould try to declare a new route.
It gave me something like below where dependencies is an array of javascript files' paths to load :
Usage
ScriptLoader.load(module.dependencies).then(function () {
demoApp.routeProvider.when(module.action, {templateUrl: 'my-template', controller: module.controller});
});
Script loader
angular.module('demoApp.services').factory('ScriptLoader', ['$q', '$rootScope', function ($q, $rootScope) {
return {
load: function (dependencies)
{
var deferred = $q.defer();
require(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}
}
}]);
Problem
I still have this javascript error "'MouseTestCtrlA' is not a function, got undefined" which means Angular could not resolved 'MouseTestCtrlA' as a registered controller.
Can anyone help me on this point please ?
Re-reading this article http://ify.io/lazy-loading-in-angularjs/ suggested to keep a $contentProvider instance inside Angular App.
I came up with this code in my app.js
demoApp.config(function ($controllerProvider) {
demoApp.controller = $controllerProvider.register;
});
It enables me to write my controller as expected in a external javascript file :
angular.module("demoApp").controller('MouseTestCtrlA', fn);
Hope this can help !

Resources