Putting app, controllers & services in separate files - javascript

I'm trying to move angular code into separate files before the project grows too big.
I tried moving the app, controllers and services into separate files but the errors stopped referencing points in the code (or they were too generic).
I have decided to put the file contents in on big <script> tag so I can work through the errors and get it working. Unfortunately I have come across this (Failed to instantiate module protonApp due to...) and don't know how to track the problem down (I'm new to angular)
The
(function () {
'use strict';
...
}());
I have round the code is because the (little) research I have done says you should have your code between these when they are in separate files.
(function () {
'use strict';
var app = angular.module('protonApp',['ui.router','protonAppControllers','protonAppServices']);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
...
}]);
app.value('debug',true);
app.run(function($rootScope,$state,$http,debug,LeftMenuService) {
...
});
}());
(function () {
'use strict';
angular.module('protonAppControllers', ['$scope','$http','LeftMenuService']);
}());
(function () {
'use strict';
angular.module('protonAppServices', ['$rootScope','$http']);
}());
(function () {
'use strict';
angular.module('protonAppControllers').controller('loginController',['$scope','$http','$state',function($scope,$http,$state){
...
}]);
}());
(function () {
angular.module('protonAppControllers').controller('surveyListController',['$scope','$http','LeftMenuService',function($scope,$http,LeftMenuService){
...
}]);
}());
(function () {
'use strict';
angular.module('protonAppControllers').controller('surveyHelpController',['$scope','$http','LeftMenuService',function($scope,$http,LeftMenuService){
...
}]);
}());
(function () {
'use strict';
angular.module('protonAppServices').service('LeftMenuService', function($http,$rootScope){
...
});
}());
EDIT
Further digging reveals I can not access $rootScope or $scope inside any of my controller files

In your module injection you don't have to add $scope and $http :
angular.module('protonAppServices', []);
Inject these in the controller but not in the module declaration

You dont need to inject anything while declaring a module, you could use them in you controller as mentioned #ThibauDL
I usually prefer declaring the modules just above the angular app declaration.
I have modified your a code in plnkr which should give you an idea as to how the code must be organized.
(function() {
'use strict';
angular.module('protonAppControllers', []);
angular.module('protonAppServices', []);
var app = angular.module('protonApp', ['ui.router', 'protonAppControllers', 'protonAppServices']);
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
//...
}
]);
app.value('debug', true);
app.run(function($rootScope, $state, $http, debug, LeftMenuService) {
//...
});
}());
(function() {
'use strict';
angular.module('protonAppServices').service('LeftMenuService', function($http, $rootScope) {
//...
});
}());
(function() {
'use strict';
angular.module('protonAppControllers').controller('loginController', ['$scope', '$http', '$state',
function($scope, $http, $state) {
$scope.login = "Hi Please login!";
// ...
}
]);
}());
(function() {
angular.module('protonAppControllers').controller('surveyListController', ['$scope', '$http', 'LeftMenuService',
function($scope, $http, LeftMenuService) {
//...
}
]);
}());
(function() {
'use strict';
angular.module('protonAppControllers').controller('surveyHelpController', ['$scope', '$http', 'LeftMenuService',
function($scope, $http, LeftMenuService) {
$scope.test = "Hxxxxi";
//...
}
]);
}());
<script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="protonApp">
<div ng-controller="loginController">
<input type="text" ng-model='login' />
</div>
</body>
Also you could now place them in separate files as you wanted.
Hope that helps.

Related

Inject factory in controller use strict and named , IIEF functions

i'm using JHispter and i saw that uses these AngularJS rules: https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
Using IIFE,Getters,Use Strict, Named Functions,ControllerAs,etc i would like to create a simple page that parse a JSON and show a movie list (title, director,duration) and the one that lasts much longer.
I've searched and tried all day but nothing works. The factory can't be used in the controller tough i inject it using $inject.
That's my index.html
<html>
<head>
<title>Hello Angular</title>
<link href="stile.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="">
</head>
<body ng-app="myApp">
<h1>Hello Angular</h1>
<div ng-controller="myController as sc">
<h1>angular JSON test</h1>
<!-- <p>Print movie list</p>
<ul >
<li ng-repeat="film in sc.elencoFilm">
{{film.title}}, {{film.director}}, {{film.time}}
</li>
</ul>
<p >Trova il film piĆ¹ lungo: {{sc.maxTimeFilm().title}} </p> -->
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="JS/app.config.js"></script>
<script src="JS/app.state.js"></script>
<script src="JS/app.service.js"></script>
<script src="JS/app.controller.js"></script>
</body>
</html>
My app.config.js
(function() {
'use strict';
angular
.module("myApp", []) ;
})();
My app.state.js
(function() {
'use strict';
angular
.module('myApp')
.config(stateConfig);
stateConfig.$inject = ['$routeProvider'];
function stateConfig($routeProvider) {
$routeProvider.when('/', {
templateUrl:"index.html",
controller:"serverController"
});
}
})();
My app.controller.js
(function () {
'use strict';
angular
.module("myApp",[])
.controller("myController", myController);
//myController.$inject = ['$scope', '$http'];
myController.$inject = ['$scope', '$http','myFactory'];
function myController($scope, $http, myFactory) {
//function myController($scope, $http){//, myFactory) {
var vm = this;
var elencoFilm={};
myFactory.getMovies().then(function (response) {
vm.elencoFilm = response;
});
vm.maxTimeFilm = getMaxTimeFilm();
function getMaxTimeFilm() { //return the longest film
}
}
})();
My app.service.js
(function () {
'use strict';
angular.module('myApp',[])
.factory('myFactory', myFactory);
myFactory.$inject = ['$scope', '$http','myFactory'];
function myFactory($scope, $http) {
console.log("sono nella factory");
return {
getMovies: function ($http) {
return $http.get('https://api.myjson.com/bins/1bgtg3');
/* .then(function (response) {
return response.data.movies;
});*/
}
}
}
})();
it always return this error:
https://docs.angularjs.org/error/$injector/unpr?p0=myFactoryProvider%20%3C-%20myFactory%20%3C-%20myController
it can't recognize myFactory into myController function!
in app.controller.js this line
function myController($scope, $http, myFactory) {
this break out the error!
Thank you for the help!! :)
Do not add empty dependency array in for module myApp in controller and factory.
Use .module('myApp') in both controller and factory, similar to your config.
By defining your modules based on functionality the myFactory service should be under a encapsulated closure referencing the main app module, hence all your factories can go under this module (ex. factories.module.js) :
(function() {
'use strict'
angular.module('myApp.factories', []);
}();
Once that module is added to your app.config
(function() {
'use strict'
angular.module('myApp', [
'myApp.factories'])
})();
It separates the concerns of your modules based on functionality following the IIFE design principle. Now reference your new module to myFactory in your service file.
(function () {
'use strict'
angular.module('myApp.factories')
.factory('myFactory', myFactory)
...
I've solved it!
i simply removed $scope from factory and removed [] in the controller definition (.module("myApp") insted of .module("myApp",[]) ).
#23rharris your advice is a best practice?
I've used the factory in each function of the controller every time i needed the JSON file :
myController.$inject = ['$scope', 'myFactory'];
function myController($scope, myFactory) {
...
vm.elencoFilm = getMovies();
function getMovies() {
myFactory.getMovies().then(function (response) {
...
...
vm.maxTimeFilm =getMaxTimeFilm();
function getMaxTimeFilm() {
myFactory.getMovies().then(function (response) {
if (response.data.movies != undefined) {
...
Is this the correct pattern for REST?

testing using karma failed : Module app is not available

I've included 3 files in my karma config : 1. angular.js, angular-mock.js, and login.spec.js
this is my login.spec.js:
describe("Hello World example", function() {
beforeEach(module("app"));
var loginCtrl,
scope;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
loginCtrl = $controller('loginCtrl', {
$scope: scope
});
}));
it('says hello world!', function () {
expect(scope.hello).toEqual("Hello");
});
});
so my login.js (controller) look like this
angular.module('app')
.controller('loginCtrl', function($scope, $rootScope, $location) {
$scope.hello = 'hello';
});
but I got Module 'app' is not available!
I don't see you creating the app module anywere. You should include the app.js and all the sources your tests need to your karma.json as well.
You just need to add this line to the top of your login.js file:
This declares the module:
angular.module('app', []);
This gets an instance of the module(as you are doing):
angular.module('app')
.controller('loginCtrl', function($scope, $rootScope, $location) {
$scope.hello = 'hello';
});
Here is a working Plunkr that is very similar:
http://embed.plnkr.co/O1otV47VxsIL5krAdUW0/preview
You also mentioned that you had added 3 files to the karma config and didn't mention the login.js. That will also need to be added.

AngularJs: use cookies inside custom service

I tried to use angular cookies in custom service, but got the error:
Unknown provider: ngCookiesProvider <- ngCookies <- checkLoginService
I store module, controllers and services in separate files.
Controller:
(function() {
'use strict';
angular
.module('app')
.controller('AuthController', AuthController);
AuthController.$inject = ['$scope', '$http', '$location', 'checkLoginService'];
function AuthController($scope, $http, $location, checkLoginService) {
/* jshint validthis:true */
var vm = this;
vm.title = 'AuthController';
$scope.login = function(user) {
/*logic*/
}
$scope.checklogin = function () {
if (checkLoginService.checkLogin()) {
/*logic*/
}
}
$scope.checklogin();
}
})();
Service:
(function () {
'use strict';
angular
.module('app')
.service('checkLoginService', ['ngCookies', checkLoginService]);
checkLoginService.$inject = ['$http'];
function checkLoginService($http, $cookies) {
return {
checkLogin: function () {
/*logic*/
}
}
}
})();
ngCookies is module not a dependency name, you should inject ngCookies in module dependency and use $cookies to get cookie object
//somewhere in app.js
angular.module('app', ['otherModules', ..... , 'ngCookies'])
Also add $cookies missing dependency inside a checkLoginService $inject array.
angular.module('app')
.service('checkLoginService', ['$cookies', checkLoginService]);
checkLoginService.$inject = ['$http', '$cookies'];
function checkLoginService($http, $cookies) {
return {
checkLogin: function () {
/*logic*/
}
}
}

How to move controller configuration into its own file?

I have the following angular configuration in the file index.js:
angular.module('ionicApp', ['ionic'])
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('entry', {
url: '/entry',
templateUrl: 'app/views/entry/entry.html',
controller: 'EntryPageController'
})
$urlRouterProvider.otherwise('/entry');
}])
.controller('EntryPageController', ['$scope', '$state', function ($scope, $state) {
$scope.navTitle = 'Entry Page';
$scope.signIn = function () {
$state.go('main.home');
}
}])
I'm trying to move the controller definition (which works in the example above) into its own file, as follows:
// file name entry-ctrl.js
(function () {
'use strict';
angular.module('ionicApp', ['ionic'])
.controller('EntryPageController', ['$scope', '$state', EntryPageController]);
function EntryPageController($scope, $state) {
$scope.navTitle = 'Entry Page';
$scope.signIn = function () {
$state.go('main.home');
}
}
})
();
In index.html I've referenced the file as
<script src="app/views/entry/entry-ctrl.js"></script>
Unfortunately, I can't get the application to behave correctly. When I use the original code, the page appears as I expect. But when I use the code in the entry-ctrl.js file, nothing appears.
Is there something else I need to do to use the code in the entry-ctrl.js file?
For the record, this is my entry.html:
<ion-view title="{{navTitle}}" class="bubble-background">
<ion-content has-header="true" padding="true">
<h1>I'm working!</h1>
<a class="button button-positive" ng-click="signIn()" ui-sref="main.home">Sign In</a>
</ion-content>
</ion-view>
It's seems that you declared your angular app twice, once in index.js and in entry-ctrl.js.
I would change it to this:
index.js
angular.module('ionicApp', ['ionic'])
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('entry', {
url: '/entry',
templateUrl: 'app/views/entry/entry.html',
controller: 'EntryPageController'
})
$urlRouterProvider.otherwise('/entry');
}])
entry-ctrl.js
(function () {
'use strict';
angular.module('ionicApp')
.controller('EntryPageController', ['$scope', '$state', EntryPageController]);
function EntryPageController($scope, $state) {
$scope.navTitle = 'Entry Page';
$scope.signIn = function () {
$state.go('main.home');
}
}
})();
in angular, you declare your app with an array of dependencies:
angular.module('ionicApp', ['ionic'])
and you reference it only by name:
angular.module('ionicApp')
Would it be possible that your Controller definition has to be above your module definition ?
(function () {
'use strict';
// First, define your Controller
function EntryPageController($scope, $state) {
$scope.navTitle = 'Entry Page';
$scope.signIn = function () {
$state.go('main.home');
}
}
// Then call it in your module
angular.module('ionicApp', ['ionic'])
.controller('EntryPageController', ['$scope', '$state', EntryPageController]);
})(this);

AngularJS Modular Set up

Up until recently, I have been throwing all my function into one large JS file. I am now trying to break these into small modules to make my application more portable per say.
I have my core js file (main.js) with the following code:
var App = angular.module("app", ['ui.bootstrap', 'angularMoment', 'chieffancypants.loadingBar', 'ngAnimate', 'ui.sortable', 'ngSanitize'], function ($interpolateProvider, $httpProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
$httpProvider.defaults.transformRequest = function (data) {
if (data === undefined) {
return data;
}
return $.param(data);
};
$httpProvider.defaults.headers.post['Content-Type'] = ''
+ 'application/x-www-form-urlencoded; charset=UTF-8';
$httpProvider.defaults.headers.post['X-Requested-With'] = ''
+ 'XMLHttpRequest';
});
In another file (i.e. blog.module.js), I have the following:
(function(window, angular, undefined) {
'use strict';
angular.module("app", [])
.controller('Blog', ['$scope', function ($scope) {
alert('test');
}]);
});
While the main.js file loads along with all its dependencies, the second one doesn't get loaded. The controller is basically not found. Can anyone give me pointers as to where I may be going wrong.?
Thanks
The sintax in blog.module.js looks like you are trying to create two modules with same name 'app'.
Change your controller module like this
(function(window, angular, undefined) {
'use strict';
angular.module("app")
.controller('Blog', ['$scope', function ($scope) {
alert('test');
}]);
});
I quote you :
App = angular.module("app", ['ui.bootstrap',
...
angular.module("app", [])
You cant redeclare a module you can either reopen it
App = angular.module("app", ['ui.bootstrap',
...
angular.module("app")
or create another one
App = angular.module("app", ['ui.bootstrap', 'app.controller'
...
angular.module("app.controller")

Categories

Resources