AngularJS - Module loading and dependency - angularjs

I have a little lack of understanding with the module loading lifecyle in my app.
A brief overview of the structure :
app [module]
common [module]
commonConfig [provider]
common [factory]
SP.Helpers [module]
SPExternalRest [provider]
... [providers]
Each module is in a separate file, call in the same order.
App module depends of common module.
Common module depends of nothing.
Helpers module depends of common.
Code where I initiate module :
angular.module('app', ['ngRoute', 'ngCookies', 'ngSanitize',
'ngResource', 'ngAnimate', 'common', 'SP.Helpers']);
angular.module('common', []);
angular.module('SP.Helpers', ['common']);
Common.js
var commonModule = angular.module('common');
commonModule.provider('commonConfig', commonConfig);
commonModule.factory('common', [
'$q',
'$rootScope',
'$timeout',
'commonConfig',
'logger',
common]);
function commonConfig() { ... }
function common($q, $rootScope, $timeout, commonConfig, logger) { ... }
SPExternalRest.js
var module = angular.module("SP.Helpers");
module.provider(serviceId, ['common', 'commonConfig', SPExternalRest]);
function SPExternalRest(common, commonConfig) { ... }
My problem, is with this conofiguration, when it loads SP.Helpers, I have this error
Error: [$injector:modulerr] Failed to instantiate module SP.Helpers due to:
Error: [$injector:unpr] Unknown provider: common
When I debug step by step, I can see it call methods in this order :
commonConfig
...
SPExternalRest
...
common
So, I understand why I have this error, but I don't understand why it doestn't finish to load the 'common' module before load 'SPExternalRest'... especially after having specified dependency between.
If you have any idea on it, I take.
Lauz
EDIT
My app.html file.
<!-- Vendor libraries -->
<script src="Scripts/jquery-1.9.1.js"></script>
<script src="/_layouts/15/MicrosoftAjax.js"></script>
<script src="/_layouts/15/init.debug.js"></script>
<script src="/_layouts/15/core.debug.js"></script>
<script src="/_layouts/15/SP.Runtime.debug.js"></script>
<script src="/_layouts/15/SP.debug.js"></script>
<script src="/_layouts/15/SP.UI.Controls.debug.js"></script>
<script src="/_layouts/15/SP.RequestExecutor.js"></script>
<!--<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.1/angular-filter.js"></script>-->
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-route.js"></script>
<script src="Scripts/angular-sanitize.js"></script>
<script src="Scripts/angular-resource.js"></script>
<script src="Scripts/angular-cookies.js"></script>
<script src="Scripts/angular-animate.js"></script>
<script src="Scripts/URI.js"></script>
<script src="Scripts/linq.js"></script>
<!-- My libraries -->
<script src="App/utils/jquery.extensions.js"></script>
<!-- Modules initialization -->
<script src="App/common/initModule.js"></script>
<script src="App/utils/initModule.js"></script>
<script src="App/filters/initModule.js"></script>
<script src="App/repositories/initModule.js"></script>
<script src="App/services/initModule.js"></script>
<!-- common angular modules -->
<script src="App/common/common.js"></script>
<script src="App/common/logger.js"></script>
<!-- App bootstraping -->
<script src="App/app.js"></script>
<script src="App/config/config.js"></script>
<script src="App/config/config.route.js"></script>
<script src="App/config/config.angular.http.js"></script>
<script src="App/config/config.exceptionHandler.js"></script>
<!-- App filters -->
<script src="App/filters/currencyEuroFilter.js"></script>
<!-- App directives -->
<script src="App/directives/keyPressEnterDirective.js"></script>
<!-- App services -->
<script src="App/utils/spUtils.js"></script>
<script src="App/services/spCsomService.js"></script>
<script src="App/services/spExternalRestService.js"></script>
<!--<script src="App/services/spRestService.js"></script>-->
<script src="App/services/spContext.js"></script>
<!-- app core -->
<script src="App/layout/workingonit.js"></script>
<script src="App/layout/spAppChrome.js"></script>
<script src="App/layout/shell.js"></script>
<script src="App/layout/header.js"></script>
<script src="App/layout/quicklaunch.js"></script>
<!-- App entities -->
<script src="App/entities/productRange.js"></script>
<script src="App/entities/product.js"></script>
<script src="App/entities/manufacturer.js"></script>
<script src="App/entities/supplier.js"></script>
<script src="App/entities/searchResult.js"></script>
<!-- App reporitories -->
<script src="App/repositories/searchRepository.js"></script>
<script src="App/repositories/productRepository.js"></script>
<script src="App/repositories/productRangeRepository.js"></script>
<!-- App controllers -->
<script src="App/productranges/productRanges.js"></script>
<script src="App/productranges/productRangesDetail.js"></script>
<script src="App/products/products.js"></script>
<script src="App/products/productsDetail.js"></script>
<script src="App/search/search.js"></script>
<script src="App/search/searchDetail.js"></script>
<script src="App/help/help.js"></script>
<script src="App/settings/settings.js"></script>
SPExternalRestService.js
(function () {
'use strict';
var serviceId = 'SPExternalRest';
var module = angular.module("SP.Helpers");
module.provider(serviceId, [
'common',
'commonConfig',
SPExternalRest
]);
function SPExternalRest(
common, commonConfig
) {
var _finalUrl = '';
var _baseUrl = '';
init();
function init() {
common.$broadcast(config.workingOnItToggleEvent, { show: true });
common.logger.log('service loaded', undefined, serviceId);
};
this.$get = ['$q', function ($q) {
var that = this;
// Methods accesible from instance
return {
setBaseUrl: function (newBaseUrl) {
_baseUrl = newBaseUrl;
},
get: function (operation, params, searches) {
var finalUrl = makeUrl(operation, params, searches);
var deferred = $q.defer();
var promise = deferred.promise;
var context = SP.ClientContext.get_current();
var request = new SP.WebRequestInfo();
request.set_url(finalUrl);
request.set_method('GET');
request.set_headers({ "Accept": "application/json;odata=verbose" });
var response = SP.WebProxy.invoke(context, request);
context.executeQueryAsync(function (data) {
if (response.get_statusCode() == 200) {
var body = response.get_body() || '{}';
try {
deferred.resolve(JSON.parse(body));
}
catch (error) {
deferred.reject(response);
}
}
else {
deferred.reject(response);
}
}, function (data) {
deferred.reject(JSON.parse(response.get_body()));
});
return promise;
}
};
}];
};
})();

Related

How to use gulp-inject to modify path of script file

gulpfile.js
gulp.task('index', function() {
var target = gulp.src('./app/index.html');
// It's not necessary to read the files (will speed up things), we're only after their paths:
var sources = gulp.src(['./app/js/**/*.js'], {
read: false
});
return target.pipe(inject(sources))
.pipe(inject(gulp.src('./app/js/**/*.js', { read: false }, { ignorePath: '/app/' })))
.pipe(gulp.dest('./build'));
});
index.html
<body ng-app="kisanApp">
<ng-view></ng-view>
<!-- inject:js -->
<script src="/app/js/app.js"></script>
<script src="/app/js/directives.js"></script>
<script src="/app/js/filters.js"></script>
<script src="/app/js/services.js"></script>
<script src="/app/js/controller/driverController.js"></script>
<script src="/app/js/controller/driversController.js"></script>
<!-- endinject -->
</body>
Here I am getting app/js/app.js rather than js/app.js. How should I modify my path so that it works perfectly?
If I understand you correctly this will solve your problem.
var gulp = require('gulp')
inject = require('gulp-inject');
gulp.task('index', function() {
gulp.src('./app/index.html')
.pipe(inject(gulp.src('./app/**/*.js', {read: false}), {ignorePath: 'app', addRootSlash: false}))
.pipe(gulp.dest('./build'));
});

Error: $controller:ctrlreg A controller with this name is not registered Service issue

My application is executed successfully without maninSvc.js. After adding this file I'm seeing errror:
angular.min.js:123 Error: [$controller:ctrlreg] http://errors.angularjs.org/1.6.5/$controller/ctrlreg?p0=MainController
at angular.min.js:7
My Code:
Index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title>
<script src="Scripts/jquery-3.2.1.min.js"></script>
<script src="Scripts/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>
<script src="Scripts/angular-resource.min.js"></script>
<link href="Scripts/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="Css/Shared.css" rel="stylesheet" />
<script src="MainController.js"></script>
<script src="mainSvc.js"></script>
</head>
<body ng-controller="MainController as vm">
<div data-ng-if="vm.success" class="success">{{vm.success}}</div>
<div data-ng-if="vm.catch" class="catch">{{vm.catch}}</div>
<div data-ng-if="vm.finally" class="finally">{{vm.finally}}</div>
</body>
</html>
MainController.js
(function() {
angular
.module('app', ['ngRoute'])
.controller('MainController', mainController);
mainController.$inject = ['mainSvc'];
function mainController(mainSvc) {
var vm = this;
mainSvc.getData()
.then(function(data) {
vm.success = "success";
}).catch(function(response) {
vm.catch = "catch";
}).finally(function() {
vm.finally = "finally";
});
}
})();
mainSvc.js
(function() {
angular
.module('app', [])
.factory('mainSvc', mainSvc);
mainSvc.$inject = ['$resource'];
function mainSvc($resource) {
var ResourceData = $resource({
query: {
isArray: true
},
get: {},
save: {
method: 'POST'
},
update: {
method: 'PATCH'
},
put: {
method: 'PUT'
},
remove: {
method: 'DELETE'
}
});
return {
getData: getData,
};
function getData() {
/// <summary>
/// Gets Data
/// </summary>
return ResourceData
.get()
.$promise;
}
}
})();
Your mainSvc.js should not have empty dependencies to the module, Then it will be considered as a new module. change it as
(function () {
angular
.module('app')
.factory('mainSvc', mainSvc);

Pulled out all my hair on an Angular unpr error

So I am getting an angular [$injector:unpr] error. Yes, I know what that normally means...I haven't defined something somewhere, or I am redefining the module over and over, or the like...but for the life of me I'm struggling to see the issue in my code.
I'm sure I'm missing something insanely basic, but after I've stared at code for a couple of hours, I go blind to it.
My HTML File:
<!DOCTYPE html>
<html ng-app="email">
<head>
<meta charset="UTF-8">
<title>Authentication</title>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700' rel='stylesheet' type='text/css'/>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
</head>
<body>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="node_modules/angular/angular.min.js"></script>
<div ng-controller="EmailAuthController as auth">
<h1>Authentication</h1>
<p>Request: [{{auth.request}}]</p>
<p>{{auth.response}}</p>
<p>{{1+2}}</p>
</div>
<script type="text/javascript" src="js/controllers/email.js"></script>
</body>
</html>
My email.js file (As you can see, I've commented out some stuff to try to isolate the issue):
/* global angular parseGet */
function parseGet(val) {
var result = '', // = "Not found",
tmp = [];
var items = location.search.substr(1).split('&');
for (var index = 0; index < items.length; index++) {
tmp = items[index].split('=');
if (tmp[0] === val) {
result = decodeURIComponent(tmp[1]);
}
}
return result;
}
(function () {
angular
.module('email', [])
.controller('EmailAuthController', [ '$scope','authFactory', function ($scope,authFactory) {
var vm = this,
req = parseGet('hash') || '';
vm.request = req;
// authFactory.validate(req)
// .then(function (response) {
// vm.response = response.data;
// });
}])
.factory('authFactory', [ '$rootScope', '$http', 'config', function ($rootScope, $http, config) {
var validate = function (hash) {
var url = config.SERVICE_URI + '/auth/email/' + hash;
return $http.get(url);
};
return {
validate: validate
};
}]);
})();
From the code you've given it appears config is not defined in your authFactory injection.
.factory('authFactory', [ '$rootScope', '$http', 'config', function(a, b, c) {} ]); // config is not defined

Marionette 'could not find template' - load external templates

I'm new with backbone, and also marionette. Idk why I'm get this error. My structure seems correct, but the error persists.
This is my index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<!-- Main App -->
<div id="main-area"></div>
<!-- Templates -->
<script id="main-tpl" src="templates/main.tpl" type="text/x-template"></script>
<!-- 3rd party Dependencies -->
<script src="vendor/jquery/dist/jquery.js"></script>
<script src="vendor/underscore/underscore.js"></script>
<script src="vendor/backbone/backbone.js"></script>
<script src="vendor/backbone.wreqr/lib/backbone.wreqr.js"></script>
<script src="vendor/backbone.babysitter/lib/backbone.babysitter.js"></script>
<script src="vendor/marionette/lib/backbone.marionette.js"></script>
<script type="text/javascript">
// External templates load
_.each(document.querySelectorAll('[type="text/x-template"]'), function (el) {
$.get(el.src, function (res) {
el.innerHTML = res;
});
});
var App = new Backbone.Marionette.Application();
_.extend(App, {
Controller: {},
View: {},
Model: {},
Page: {},
Scrapers: {},
Providers: {},
Localization: {}
});
App.addRegions({
Main: '#main-area'
});
App.addInitializer(function (options) {
var mainView = new App.View.Main();
try {
App.Main.show(mainView);
} catch(e) {
console.error('Error on Show Main: ', e, e.stack);
}
});
App.View.Main = Backbone.Marionette.Layout.extend({
template: '#main-tpl'
});
(function(App) {
'use strict';
App.start();
})(window.App);
</script>
</body>
and my template/main.tpl is only test html.
<div>sounds</div>
All 3rd party dependencies paths are correct.
The error that appears is this:
Error: Could not find template: '#main-tpl'
Can someone tell me where am I wrong?
Thanks.
EDIT:
I think the problem is because $.get is async and the template load after backbone try to render, how can I solve this?
You can update your HTML and replace
<script id="main-tpl" src="templates/main.tpl" type="text/x-template"></script>
with
<script id="main-tpl" type="text/html">
--- template code ---
</script>
Or use requireJs !text plugin to load template files into marionette views.
The problem is that the template loads after the app initialization.
Instead, try this:
$(function () {
var tplList = document.querySelectorAll('[type="text/x-template"]');
var tplCounter = 0;
_.each(tplList, function (el) {
$.ajax({
'url': el.src,
success: function (res) {
el.innerHTML = res;
++tplCounter;
if(tplCounter == tplList.length){
App.start();
}
}
});
});
});
define(['marionette','tpl!cell.tpl'],function(tpl){
var Mn = Backbone.Marionette;
var MyView = Mn.View.extend({
className: 'bg-success',
template: tpl,
regions: {
myRegion: '.my-region'
}
});
})
var model = new Backbone.Model({});
var myView = new MyView({model:model});

Phonegap with Angular: deviceready not working properly

I believe I have set everything for Angular to work in Phonegap, but apparently the deviceready function is not having the behavior that I expect.
So here is how I set:
index.html
<html ng-app="app">
<head>
<script type="text/javascript" src="js/lib/angular.min.js"></script>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/lib/ready.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body>
<div class="header" ng-controller="HeaderController">
<h3 id="logo"><img src="img/logo.png"/></h3>
<p>{{title}}</p>
<button ng-click="changeTitle()"></button>
</div>
</body>
</html>
app.js
$app = angular.module('app', ['fsCordova']);
$app.config(function($compileProvider){
$compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
});
$app.controller('HeaderController', function($scope, CordovaService) {
CordovaService.ready.then(function() {
console.log("Setting the title");
$scope.title = "This title";
$scope.changeTitle = function() {
console.log("Changing the title");
$scope.title = "Title changed";
}
});
});
ready.js from: http://www.ng-newsletter.com/posts/angular-on-mobile.html#native
angular.module('fsCordova', [])
.service('CordovaService', ['$document', '$q',
function($document, $q) {
var d = $q.defer(),
resolved = false;
var self = this;
this.ready = d.promise;
document.addEventListener('deviceready', function() {
resolved = true;
d.resolve(window.cordova);
});
// Check to make sure we didn't miss the
// event (just in case)
setTimeout(function() {
if (!resolved) {
if (window.cordova) d.resolve(window.cordova);
}
}, 3000);
}]);
The title is appearing the way it is {{title}}, not its value. When I click the button, nothing happens, not even the debug logs on the console. Any tips how to set Angular on Phonegap? Thanks.
Apparently on angular 1.2 the urlSanitizationWhitelist doesn't exist anymore.
So I just had to remove the $compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/); line and it worked

Resources