I have an AngularJS web application. Everything works fine but I've noticed this error during start up on the console log:
Basically it complains about a module not being found, a module with an empty name?
Module '' is not available! You either misspelled the module name or
forgot to load it. If registering a module ensure that you specify the
dependencies as the second argument.
the exception creates automatically a URL to the online help, of course the p0 parameter is emtpy
https://docs.angularjs.org/error/$injector/nomod?p0=
Inspecting further if I follow the stack trace I end up in this file here (it's very long, so for convenience I'll crop it
angular.module("").run(['$templateCache', function(a) { a.put('/app/components/upload/upload.html', '<et-top-nav></et-top-nav><div class="uploadPage"><div style="margin-top:3.7em"><et-uploader></et-uploader>....
The parameter for the module() function looks to be an empty string
The name of the app is "app", not an empty string
any clue on what's going on here?
EDIT
App initialization:
(function() {
angular
.module("app", ["ngNewRouter", "ngSanitize", "ngFileUpload", "ngToast", "ngAnimate", "ui.bootstrap"])
.config(["$locationProvider", configureLocationProvider])
.config(["$httpProvider", configureHttpProvider])
.config(["ngToastProvider", configureToastProvider])
.controller("AppController", ["$router", "$rootScope", "onChartUrlChange", appController])
.run(["onWindowResize", setup]);
function appController($router, $rootScope, onChartUrlChange) {
$router.config([
{ path: "/", components: {"default":"chartPicker"} },
{ path: "/upload", components: {"default":"upload"} },
{ path: "/batch/:groupId", components: {"default":"chart"} }
]);
// AngularJS doesn't update components on frag change, so we do it ourselves
$rootScope.$on("$locationChangeSuccess", function() {
onChartUrlChange.updateChart();
});
$rootScope.$on("$zoomUrlChanged", function() {
onChartUrlChange.updateChart();
});
}
The template file generated by Broccoli doesn't include the name of the app (which sould be "app")
angular.module("").run(['$templateCache', function(a) { a.put('/app/components/chart-picker/chart-pi...
and this is causing the exception
Related
I have a difficult case which was organized from an old angularjs and angular8, besides it's was also limited in the extensive refactoring to resolve in code of micronization.And the code of angularjs cannot be changed.
In the end I choose the library ngx-planet that is closest to my situation, but i got this error
Issue:
When I then local run it, I get this error message.
I have tested this way of writing under angularjs and angular8 code without planet library, it can work, but after using planet, the aforementioned error occurred.
After searching, it was found that the reasons for this error message are known as the following 6 types:
Barrel index
Circularity dependency
Forgot to enable polyfills import'core-js/es6/reflect'
Injectable decorator incorrect usage (EX: missing # or capital & lower case error etc...)
Tsconfig does not configure emitDecoratorMetadata
Decorate parameter type use any in your constructor
The first 5 have been excluded, I suspect it is the last, because of this Configuring Dependency Injection in Angular
But I am confused, whether a certain configuration of planet causes parameter type to fail?
Code Structure:
1. There is a common service exported from angularjs
(File name: angular1-root-module.js)
(function () {
angular.module('angular1', [
'angular1.export-service'
]);
angular.module('angular1.export-service', []);
angular.module('angular1.export-service').factory('Angular1ExportService', Angular1ExportService);
Angular1ExportService.$inject = [];
function Angular1ExportService() {
function outPutString() {
return 'I from Angular1 export service string';
}
return {
outPutAngular1String: outPutString,
};
}
})();
2. Inject into the class named Angular1InjectorService through the factory provider and depend on angularjs's $injector
export function Angular1InjectorServiceFactory(injector: any) {
return new Angular1InjectorService(injector);
}
export const Angular1InjectorServiceProvider = {
provide: Angular1InjectorService,
useFactory: Angular1InjectorServiceFactory,
deps: ['$injector']
};
#Injectable()
export class Angular1InjectorService {
// I think probably this injector of type is any cause
constructor(private angular1Injector: any) {
}
getService(serviceName: String) {
return this.angular1Injector.get(serviceName);
}
}
3. Then inject into the common AppBaseService
#Injectable()
export class AppBaseService {
readonly angular1InjectorService: Angular1InjectorService;
readonly testService: any;
constructor(readonly injector: Injector) {
this.angular1InjectorService = this.injector.get(Angular1InjectorService);
this.testService = this.angular1InjectorService.getService('Angular1ExportService');
}
testGetAngular1String() {
console.log('app base service is work!');
return this.testService.outPutAngular1String();
}
}
4. Then the service of the sub app inherits AppBaseService, and obtains the method that exists in angularjs
export class App1RootService extends AppBaseService {
constructor(readonly injector: Injector) {
super(injector);
}
GetLogAngular1String() {
console.log('app1 root service is work!');
return this.testGetAngular1String();
}
}
5. Portal root planet config
this.planet.registerApps([
{
name: 'app1',
hostParent: '#app-host-container',
routerPathPrefix: '/app1',
selector: 'app1-root-container',
resourcePathPrefix: '/static/app1',
preload: settings.app1.preload,
switchMode: settings.app1.switchMode,
loadSerial: true,
manifest: '/static/app1/manifest.json',
scripts: [
'main.js'
],
styles: [
],
}
]);
6. Sub app1 main config
defineApplication('app1', (portalApp: PlanetPortalApplication) => {
return platformBrowserDynamic([
{
provide: PlanetPortalApplication,
useValue: portalApp
},
{
provide: AppRootContext,
useValue: portalApp.data.appRootContext
}
])
.bootstrapModule(App1RootModule)
.then(appModule => {
return appModule;
})
.catch(error => {
console.error(error);
return null;
});
});
Issue related resources:
EXCEPTION: Can't resolve all parameters
Uncaught Error: Can't resolve all parameters for
After upgrade Angular to v8: Can't resolve all parameters for Component:
Intact issue code:
Stackblitz
Github
I have not found an answer, and already have the official github open issue, but hope to get more help
Thanks.
I am using gulp to run and build to run my application. I am getting file contents using $http service in my index.js file and then setting value of a variable like
window.variablex = "http://localhost:8080/appname".
here is how I am doing it (in index.js)
(function ()
{
'use strict';
angular
.module('main')
.controller('IndexController', IndexController);
function IndexController($http){
$http.get('conf/conf.json').success(function(data){
window.variable = data.urlValue;
}).error(function(error){
console.log(error);
});
}
});
And I've created a factory to call the rest APIs of my backend application like
(function(){
'use strict';
angular
.module('main')
.factory('testService',['$resource',testService]);
function agentService($resource){
var agents = $resource('../controller/',{id:'#id'},
{
getList:{
method:'GET',
url:window.variable+"/controller/index/",
isArray:false
}
});
Now, I except a rest call to made like
http://localhost:8080/appname/controller
But it always sends a call like http://undefined/appname/controller which is not correct.
I can get the new set value anywhere else, but this value is not being set in resource service objects somehow.
I am definitely missing something.
Any help would be much appreciated
As you are using Gulp, I advise you to use gulp-ng-config
For example, you have your config.json:
{
"local": {
"EnvironmentConfig": {
"api": "http://localhost/"
}
},
"production": {
"EnvironmentConfig": {
"api": "https://api.production.com/"
}
}
}
Then, the usage in gulpfile is:
gulp.task('config', function () {
gulp.src('config.json')
.pipe(gulpNgConfig('main.config', {
environment: 'production'
}))
.pipe(gulp.dest('.'))
});
You will have this output:
angular.module('myApp.config', [])
.constant('EnvironmentConfig', {"api": "https://api.production.com/"});
And then, you have to add that module in your app.js
angular.module('main', [ 'main.config' ]);
To use that variable you have to inject in your provider:
angular
.module('main')
.factory('testService', ['$resource', 'EnvironmentConfig', testService]);
function agentService($resource, EnvironmentConfig) {
var agents = $resource('../controller/', {id: '#id'},
{
getList: {
method: 'GET',
url: EnvironmentConfig + "/controller/index/",
isArray: false
}
});
}
#Kenji Mukai's answer did work but I may have to change configuration at run time and there it fails. This is how I achieved it (in case anyone having an issue setting variables before application gets boostrap)
These are the sets that I followed
Remove ng-app="appName" from your html file as this is what causing problem. Angular hits this tag and bootstraps your application before anything else. hence application is bootstratped before loading data from server-side (in my case)
Added the following in my main module
var injector = angular.injector(["ng"]);
var http = injector.get("$http");
return http.get("conf/conf.json").then(function(response){
window.appBaseUrl = response.data.gatewayUrl
}).then(function bootstrapApplication() {
angular.element(document).ready(function() {
angular.bootstrap(document, ["yourModuleName"]);
});
});
This will load/set new values everytime you refresh your page. You can change conf.json file even at runtime and refreshing the page will take care of updating the values.
I am using angular-translate in my custom directive template, for example:
<!-- directive template -->
<button>{{"ers.diagramComponent.resizeOriginalButton" | translate}</button>
My json that maps to this translate value:
{
"ers.diagramComponent.resizeOriginalButton": "Original"
}
I was originally getting this error:
Error: [$injector:unpr] Unknown provider: translateFilterProvider <- translateFilter
I corrected that by adding:
<!-- This is at the top level, runs before all tests -->
describe("Directive", function () {
beforeEach(angular.mock.module("directive"));
var mockFilter = function (value: any) {
return value;
};
beforeEach(function () {
angular.mock.module(function ($provide:any) {
$provide.value("translateFilter", mockFilter);
});
});
});
Found the above here: How to mock angular translate filter in unit tests for directives
I am trying to now get that translate value to match in my karma/jasmine tests. My failing test looks something like this:
var actualSizeHtml = diagramDirective.find("button").html();
expect(actualSizeHtml).toEqual("Original");
My failing test:
Expected 'ers.diagramComponent.resizeOriginalButton' to equal 'Original'.
So basically I can't figure out how to translate "ers.diagramComponent.resizeOriginalButton" so that it equals "Original", which is what the test is looking for.
Here is my config for setting up the $translateProvider in the components, the resources folder holds the json for my key/value pairs:
angular.module("app",["pascalprecht.translate"]).config(["tmhDynamicLocaleProvider", function(tmhDynamicLocaleProvider) {
$translateProvider.useStaticFilesLoader({
prefix: "resources/locale-",
suffix: ".json"
});
$translateProvider.preferredLanguage("en-us");
$translateProvider.useSanitizeValueStrategy("escape");
}]);
But that configuration has nothing to do with my tests.
It seems that your tests know nothing about "pascalprecht.translate" module, which contains translate filter. You need to add "pascalprecht.translate" module as dependency to "directive" module or do somethig like this:
describe("Directive", function () {
beforeEach(angular.mock.module("directive", "pascalprecht.translate"));
var mockFilter = function (value: any) {
return value;
};
beforeEach(function () {
angular.mock.module(function ($provide:any) {
$provide.value("translateFilter", mockFilter);
});
});
});
Also, you can write just
module("directive", "pascalprecht.translate")
instead of
angular.mock.module("directive", "pascalprecht.translate")
I'm using gulp-angular-templatecache to generate a templateCache.js file which combines all my HTML template files into 1. (my full gulpfile)
After injecting that new module into my app, my Directives will automatically pick up the templates and I won't need to add the partial .html files into my build folder.
The problem is that the leading folder path is getting cut off, see my example below:
The paths in my Directives:
templateUrl : "panels/tags/tagsPanel.html"...
templateUrl : "header/platform_header/platformHeader.html"...
The paths in my produced templateCache file:
$templateCache.put("tags/tagsPanel.html"...
$templateCache.put("platform_header/platformHeader.html"...
^ panels and header are getting lost.
I'm trying to write a function that will fix that in my Gulpfile.
The config section of my Gulpfile:
var config = {
srcPartials:[
'app/beta/*.html',
'app/header/**/*.html',
'app/help/*.html',
'app/login/*.html',
'app/notificaitons/*.html',
'app/panels/**/*.html',
'app/popovers/**/*.html',
'app/popovers/*.html',
'app/user/*.html',
'app/dashboard.html'
],
srcPaths:[
'beta/',
'header/',
'help/',
'login/',
'notificaitons/',
'panels/',
'popovers/',
'popovers/',
'user/',
'dashboard.html'
],
destPartials: 'app/templates/'
};
My html-templates gulp.task
gulp.task('html-templates', function() {
return gulp.src(config.srcPartials)
.pipe(templateCache('templateCache.js', {
root: updateRoot(config.srcPaths)
},
{ module:'templateCache', standalone:true })
).pipe(gulp.dest(config.destPartials));
});
function updateRoot(paths) {
for (var i = 0; i < paths.length; i++) {
// console.log(paths);
console.log(paths[i]);
return paths[i];
}
}
^ The above is working, in that it uses the root option in gulp-angular-templatecache to append a new string in front of the template paths.
Problem is my code above returns once and updates all the paths to the first item in the paths Array which is beta/.
How would you write this so that it correctly replaces the path for each file?
Figured it out! I should not have been using exact folder names, but globs ** in my config
var config = {
srcTemplates:[
'app/**/*.html',
'app/dashboard.html',
'!app/index.html'
],
destPartials: 'app/templates/'
};
The updated gulp.task:
gulp.task('html-templates', function() {
return gulp.src(config.srcTemplates)
.pipe(templateCache('templateCache.js', { module:'templateCache', standalone:true })
).pipe(gulp.dest(config.destPartials));
});
Now the output is correct:
$templateCache.put("beta/beta.html"...
$templateCache.put("header/control_header/controlHeader.html"...
$templateCache.put("panels/tags/tagsPanel.html"...
I ran into a similar issue, but in my case, it wasn't possible to use the same directory for all the gulp.src entries.
There is a solution that will work all those folders
return gulp.src(['public/assets/app1/**/*.tpl.html', 'public/assets/common_app/**/*.tpl.html'])
.pipe(templateCache({
root: "/",
base: __dirname + "/public",
module: "App",
filename: "templates.js"
}))
.pipe(gulp.dest('public/assets/templates'))
That presumes the gulpfile is one directory up from the public directory. It will remove the base string from the full path of the files from src.
Base can also be a function that will be passed the file object which could be helpful in more complicated situations. It's all around line 60 of the index.js in gulp-angular-templatecache
You can also use this gulp plugin which can read your routes, directives and replace the templateUrl with the template referenced in the templateUrl.
This will remove all headache regarding handling templateUrl in your application. This uses relative url to directive js files instead of absolute url.
src
+-hello-world
|-hello-world-directive.js
+-hello-world-template.html
hello-world-directive.js:
angular.module('test').directive('helloWorld', function () {
return {
restrict: 'E',
// relative path to template
templateUrl: 'hello-world-template.html'
};
});
hello-world-template.html:
<strong>
Hello world!
</strong>
gulpfile.js:
var gulp = require('gulp');
var embedTemplates = require('gulp-angular-embed-templates');
gulp.task('js:build', function () {
gulp.src('src/scripts/**/*.js')
.pipe(embedTemplates())
.pipe(gulp.dest('./dist'));
});
gulp-angular-embed-templates will generate the following file:
angular.module('test').directive('helloWorld', function () {
return {
restrict: 'E',
template:'<strong>Hello world!</strong>'
};
});
The error ONLY occurs under a special routing circumstance when the layout (see gist link) is called by the router following a login processed in a different controller and routed here by the global event mechanism.
Everything is fine as long as an existing session is reused and there is NO Logon processed.
main code in this gist ( error at line #113 "this.headerRegion" not defined
Code blocks coming to the gist module , from logon and from router...
loginSuccess: function (user) {
vent.trigger('user:login'); //notify all widgets we have logged in
app.router.navigate('home', { trigger: true });
}
...
return marionette.AppRouter.extend({
routes: {
'home' : 'home',
...
},
home: function() {
this._showPage('home');
},
...
_showPage: function (pageName, options) {
console.log("RouterShow " +pageName);
var that = this;
//make sure we are authenicated, if not go to login
if (!Parse.User.current())
pageName = 'login';
require(['./pages/' + pageName + '/Controller'], function (PageController) {
if (that.currentPageController) {
that.currentPageController.close();
that.currentPageController = null;
}
// line below loads the layout in the gist link
that.currentPageController = new PageController(options);
that.currentPageController.show(app.regionMain)
.fail(function () {
//display the not found page
that.navigate('/not-found', { trigger: true, replace: true });
});
});
}
...
define([
'marionette',
'./Layout',
'app'
], function (
Marionette,
Layout,
app
) {
'use strict';
return Marionette.Controller.extend({
show: function (region) {
var that = this, d = new Marionette.$.Deferred();
region.show(new Layout({ })); //this layout in gist link
return d.promise();
}
});
});
pageController.show() near the end of the above block calls the Layout region in the gist
To recreate the error that ONLY OCCURs following a logon, I do the following:
Show compoundView #1 at line #57 of the gist.
click in compound view #1 firing event at line #40 of the gist ('roleList:getuser',)
swap new views #2 into EXISTING regions used for the first views at lines #113, 114
ERROR at 113, "this.headerRegion" no longer exists in the layout!
Discussion - now IMO Layout extends Marionett.ItemView and from the source, it should always have the regions defined before calling init. The constructor checks for undef "this.headerRegion" at line #23 of the gist.
My code reimplements the superclass constructor in lines 18 - 23 of the gist and it looks like "headerRegion" and "mainRegion" attributes are always defined. But, the error is :
Uncaught TypeError: Cannot call method 'show' of undefined
Layout.js:113 Marionette.Layout.extend.getUserRelation
The region properties like 'headerRegion' in your case are only available after render(), not just initialize(). From the Marionette docs:
Once you've rendered the layout, you now have direct access to all of
the specified regions as region managers.
You must be triggering those events ('roleItem:getrole', etc.) before the layout is rendered in logic outside the gist. Instead you'll need to render first if you want to implement getUserRelation() in this way.