I am in the process of migrating our .NET Framework project over to .NET Core. And where we previously relied on the BundleTable tools in .NET Framework. We are now using webpack.
I have a directive that uses a package 'angularjs-dragula'. The webpack entry definition is as follows
'bundles/grouping':
[
"./Scripts/angularjs-dragula.js",
"./App/components/grid.directive.js",
"./App/components/inline-edit.directive.js",
"./App/services/grouping.service.js",
"./App/components/grouping/grouping.directive.js"
],
I initialize the directive as follows:
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
As it is, the page never loads grouping.directive. And there are no errors. Unless i remove the dragula file in the webpack entrypoint. The directive will then load, but complain:
ReferenceError: angularDragula is not defined[Learn More]
I have tried relying on webpack to import the package, and removed it from the entry definition. I installed angularjs-dragula into my node_modules, and used
var angularDragula = require('angularjs-dragula');
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
However this results in the same behavior.
The angularjs-dragula package works, since we were using it before the move to webpack. However now it seems to be silently failing, and taking the rest of the directive with it?
How can I begin to diagnose this issue?
The AngularJS wrapper for Dragula is unusual in that it places on global scope a function named angularDragula. That function registers the dragula module with AngularJS when the function is invoked with angular as an argument. It returns a string with the module name "dragula".
angularDragula(angular)
angular.module("app",["dragula"])
.run(function(dragulaService) {
console.log(dragulaService);
})
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angularjs-dragula/dist/angularjs-dragula.js"></script>
<body ng-app="app">
<h1>Hello AngularJS!</h1>
</body>
the page never loads grouping.directive
How can I begin to diagnose this issue?
I would use the Developer Console to insert breakpoints. Then examine variables.
The above example loads AngularJS with Dragula and successfully logs the dragularService.
Related
I searched a lot of posts and also the official Angular documentation, but I'm not able to get an AngularJS service running in Angular. I finally came to this page https://angular.io/api/upgrade/static/UpgradeModule#examples which seems to explain exactly what I need, but when doing all those steps I'm getting:
ERROR Error: Trying to get the AngularJS injector before it being set.
My impression is that this example is not quite complete. E.g. there is no hint were the (old) AngularJS framework must be loaded. My service looks like angular.module('my-module').service('my-service', ... thus angular needs to be defined, otherwise I'm getting an error. Furthermore many examples assume that the AngularJS code is written in TypeScript. In my case this is not true (just plain Javascript).
Unfortunately with Angular 9 there is an additional issue with the #angular/upgrade module which is not mentioned anywhere and can only be solved by disabling the new Ivy compiler in tsconfig.app.json, otherwise the compiler will throw Error: Error on worker #1: Error: getInternalNameOfClass() called on a non-ES5 class: expected UpgradeComponent to have an inner class declaration:
"angularCompilerOptions": {
"enableIvy": false
}
I'd really appreciate if somebody could post a complete example on what exactly must be done in order to run an AngularJS service in an Angular component.
UPDATE [6th July 2020]
Here you can find a GitHub repo which you can clone, to reproduce the behavior: https://github.com/berkon/angularjs-service-upgrade-test. I should also mention that I'm using the Electron framework and started based on this repo https://github.com/maximegris/angular-electron but I guess that shouldn't matter in this case.
Finally I got it working! It was really really cumbersome to figure this all out. A lot of things aren't mentioned in most tutorials and even in the official Angular guide there are only code snippets which make it hard for Angular newbies to guess where to put all that stuff. Also the bootstraping is not explained correctly. Furthermore all tutorials assume that the "old" AngularJS code is already written in TypeScript, which makes it even harder to find the right way/order to load/bootstrap/import all that stuff. Finally there seems to be an issue with the #angular/upgrade module in combination with the new Ivy compiler in Angular 9. It throws the error mentioned below. Thus it must be disabled to get things working. A real pain!!!
So roughly these are the steps:
install the angular and #angular/upgrade node modules
load all .js modules including AngularJS in the script section of angular.json
interrupt the regular Angular bootstrap process by removing the bootstrap section from #NgModule and bootstrap AngularJS via ngDoBootstrap manually. First bootstrap
AngularJS, afterwards bootstrap the AppComponent class. This way the service is available at AppComponent initialization. Otherwise you'll get an injection error!
Add a new provider in providers [] section to get access to the new service
Now the new (upgraded) service can be injected in the constructor of AppComponent
Its quite a lot of work to perform all steps below manually, but I listed them for reference. Here you can find a GitHub repo where you can clone a working app. Don't be surprised! This repo uses the Electron framework (electronjs.org). But don't worry this doesn't have any influence on my findings: https://github.com/berkon/angularjs-service-upgrade-test
And here is the step-by-step guide:
Prerequistes
execute npm install angular --save
execute npm install #angular/upgrade --save
in tsconfig.app.json add "enableIvy": false to angularCompilerOptions to avoid getting:
Error: getInternalNameOfClass() called on a non-ES5 class: expected UpgradeComponent to have an inner class declaration
add "node_modules/angular/angular.js" and the Javascript file which contains your AngularJS service (in this case "src/app/angular-js-service.js") to the scripts [] array in angular.json
app.module.ts
add ApplicationRef to the import brackets of #angular/core
add import { UpgradeModule } from '#angular/upgrade/static'
add UpgradeModule to imports [] array of #NgModule
remove bootstrap section completely from #NgModule and replace it with this: entryComponents: [AppComponent]
add this to the providers [] array in #NgModule and make sure to replace myService with the correct name of your service:
{ provide: 'myService', useFactory: (i: any) => { return i.get('myService') }, deps: ['$injector'] }
replace the constructor of AppModule with this:
constructor ( public upgradeModule: UpgradeModule ) {}
add this to the AppModule class and make sure to replace ajsAppModule with the name of your AngularJS main app module:
ngDoBootstrap ( appRef: ApplicationRef ) {
this.upgradeModule.bootstrap(document.body, ['ajsAppModule'], { strictDi: true } )
appRef.bootstrap ( AppComponent )
}
app.component.ts
add Inject to the import brackets at #angular/core
in the AppComponent class change the constructor to this and make sure to replace myService with the name of your AngularJS service
constructor ( #Inject('myService') myService: any ) {
myService.doSomething()
}
I had this same error and I solved it in my app, however I cannot remember exactly why this was happening (sorry, it was a long time ago). I wasn't upgrading services, instead I was downgrading.
Here's my app.module.ts I've added comments to the parts that were critical to get this working, I hope there may be a hint for you here. Note that I used the Angular CLI to generate the app.
setAngularJSGlobal(angular);
// Configure the angularjs app (yours might be defined elsewhere)
const app = angular.module('app', [MyFormsModule, AngularMaterialModule]);
app.run(RunAddressAutocompleteConfig);
app.run(RunDynamicQueryConfig);
// Downgrade Angular AppComponent so AngularJS can render it after bootstrapping
// my app used an Angular component as the root
app.directive('appRoot', downgradeComponent({ component: AppComponent }));
// Downgrade Angular services
app.factory('api', downgradeInjectable(ApiService));
app.factory('dynamicQuery', downgradeInjectable(DynamicQueryService));
#NgModule({
declarations: [
AppComponent,
FormDirective,
FormPageComponent,
FormsListPageComponent,
RouterLinkPreserveQueryParamsDirective,
FormEmptyStatePageComponent,
],
imports: [BrowserModule, UpgradeModule, AppRoutingModule, HttpClientModule, CommonModule],
// This was absolutely necessary for bootstrapping my app in this way
// I encountered errors otherwise
providers: [
{
provide: '$scope',
useExisting: '$rootScope',
},
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
entryComponents: [AppComponent],
})
export class AppModule implements DoBootstrap {
constructor(private readonly upgrade: UpgradeModule) {}
ngDoBootstrap(appRef: ApplicationRef) {
this.upgrade.bootstrap(document.body, [app.name], { strictDi: true });
appRef.bootstrap(AppComponent);
}
}
index.html
<body>
<app-root></app-root>
</body>
I need to mask my input in my application. I was using ngMask in angularjs. But i found an issue in ngMask is that if we update the mid value the cursor move to end. I tried to resolve the issue but did not find anything. Even on github this issue has reported but still not resolved. Here is the link
ngMask Issue
Then i decided to use another mask library. I found ui-mask and trying to use in my application but i am getting error when i include in my project. My application is in angularjs and i am using requirejs as well to load the modules.
This is what i have done in main.js:
paths: {
...////
"angular-ui-mask": "../../lib/ui-mask/ui-mask.min",
},
'angular-ui-mask': {
deps: ['angular'],
exports: 'angular-ui-mask'
},
in app.js i have done:
var app = angular.module("app",
[
"ui.router",
"mobile-angular-ui",
"scrollable-table", //for alert triggering
"rzModule", //slider for SEMI diagram
"isteven-multi-select",
"ui.bootstrap",
"cgBusy", "dndLists", 'apm-kpi-widget',
'angular.filter',
"pascalprecht.translate",
"jQueryScrollbar",
"ui.checkbox",
"angular-ui-mask"
])
This is exact i was doing for ngMask. But in this case i am getting error
[$injector:modulerr] http://errors.angularjs.org/1.5.5/$injector/modulerr?
at angular.js:38
at angular.js:4587
at q (angular.js:322)
at g (angular.js:4548)
at bb (angular.js:4470)
at c (angular.js:1746)
at Object.yc [as bootstrap] (angular.js:1767)
at HTMLDocument.<anonymous> (angularAMD.js:449)
at i (jquery-1.12.3.min.js?v=1531811705531:2)
at Object.add [as done] (jquery-1.12.3.min.js?v=1531811705531:2)
What's the issue?
I'm using yeoman generator for scaffolding angular web application with requirejs. Its working fine but when I tried to concat and minifying all the js file into a single file through grunt task runner its started giving me above mentioned error. I've researched online about the issue and common solution is I may be mis-spelled any service injecting in the module or service does not exists, I've cross checked again all the spelling, quotation marks etc everything seems fine but still I'm unable to resolve this issue.
Here is my app.js file where my main module with dependencies is listed.
return angular
.module('arteciateYeomanApp', [
'arteciateYeomanApp.controllers.MainCtrl',
'arteciateYeomanApp.controllers.AboutCtrl',
'arteciateYeomanApp.services.Xhr',
'arteciateYeomanApp.services.Common',
'arteciateYeomanApp.controllers.ArtworkCtrl',
'arteciateYeomanApp.controllers.AddAccountCtrl',
'arteciateYeomanApp.controllers.AddArtgroupCtrl',
'arteciateYeomanApp.controllers.AddArtistCtrl',
'arteciateYeomanApp.controllers.AddArtworkCtrl',
'arteciateYeomanApp.controllers.AddCampaignsCtrl',
'arteciateYeomanApp.controllers.AddGenreCtrl',
'arteciateYeomanApp.controllers.AddInstitutionCtrl',
'arteciateYeomanApp.controllers.AdminSignupCtrl',
'arteciateYeomanApp.controllers.ArtistInfoCtrl',
'arteciateYeomanApp.controllers.DirectUserSignupCtrl',
'arteciateYeomanApp.controllers.ErrorCtrl',
'arteciateYeomanApp.controllers.ForgotPasswordCtrl',
'arteciateYeomanApp.controllers.GroupBuyingCtrl',
'arteciateYeomanApp.controllers.LoginCtrl',
'arteciateYeomanApp.controllers.AdminLoginCtrl',
'arteciateYeomanApp.controllers.ResetPasswordCtrl',
'arteciateYeomanApp.controllers.SignupCtrl',
'arteciateYeomanApp.controllers.UnblockUserCtrl',
'arteciateYeomanApp.controllers.UpdatePasswordCtrl',
'arteciateYeomanApp.controllers.DashboardCtrl',
'ngRoute','ngResource']).config(.....);
here is grunt task which I'm running for minifying the js files.
registering task
grunt.registerTask('dev', ['requirejs' ]);
Here is task running script
requirejs : {
compile : {
options : {
baseUrl : "<%= yeoman.app %>/scripts",
mainConfigFile : "<%= yeoman.app %>/scripts/main.js",
name : "main",
out : "requireArterciate.js"
}
}
}
Please let me know if I'm doing something wrong here.
If you need to minify the angularjs code, then use the following standard format syntax to define the controller and to inject the dependencies. Refer Dependency Injection
angular.module('test').controller('testController', testController);
testController.$inject = ['$scope', '$rootScope'];
function testController($scope, $rootScope) {};
I have a really weird issue with my AngularJS app on iPad / iPhone safari.
The issue occurs only of first load (after clearing history / website data).
The issue that the application wont start at all - I get a white page and the console (from MacBook develop tools) is full with errors,
Sometimes I'm getting lots of
TypeError: undefined is not an object (evaluating 'd.module')
ReferenceError: Can't find variable: angular
TypeError: undefined is not an object (evaluating 'd.$$minErr')
ReferenceError: Can't find variable: angular
TypeError: undefined is not an object (evaluating 't.noop')
ReferenceError: Can't find variable: angular
ReferenceError: Can't find variable: angular
...
Sometimes I'm getting Error: $injector:unpr - Unknown Provider
And sometimes Error: $injector:nomod - Unknown Provider
But if I hit page refresh after getting the white page / errors - all works just fine.
This is part of the third party js libs/plugins I include on my index.html
<script src="resources/plugins/head.load.min.js"></script>
<script src="resources/plugins/modernizr-custom.js"></script>
<script src="resources/lib/jquery/jquery-2.1.0.min.js"></script>
<script src="resources/lib/angular/angular.min.js"></script>
<script src="resources/lib/angular/angular-resource.min.js"></script>
<script src="resources/lib/angular/angular-route.min.js"></script>
<script src="resources/lib/angular/angular-animate.min.js"></script>
<script src="resources/lib/angular-translate/angular-translate.min.js"></script>
<script src="resources/lib/angular-translate/angular-translate-loader-static-files.js"></script>
<script src="resources/lib/angular-ui/ui-bootstrap-custom-tpls-0.14.1.min.js"></script>
<script src="resources/lib/ng-table/ng-table.min.js"></script>
<script src="resources/lib/file-upload/ng-file-upload-shim.min.js"></script>
<script src="resources/lib/file-upload/ng-file-upload.min.js"></script>
I'm really lost here...
Another thing: I have noticed on my Mac (Resources->Scripts) that if I open a file, lets say Resources->Scripts->FileNameOne.js the content is actually of another file FileNameTwo.js ??? is it a flaw of the dev tools of the Mac that confuses the names/content or can it be related to the problem???
Any Ideas?
Here is the complete solution with Grunt
Content of the Gruntfile.js
'use strict';
module.exports = function(grunt){
grunt.initConfig({
concat: {
dist: {
src: ['WebContent/resources/plugins/head.load.min.js', 'WebContent/resources/plugins/modernizr-custom.js',
'WebContent/resources/lib/jquery/jquery-2.1.0.min.js',
'WebContent/resources/lib/angular/angular.min.js', 'WebContent/resources/lib/angular/angular-resource.min.js', 'WebContent/resources/lib/angular/angular-route.min.js', 'WebContent/resources/lib/angular/angular-animate.min.js',
'WebContent/resources/lib/angular-translate/angular-translate.min.js', 'WebContent/resources/lib/angular-translate/angular-translate-loader-static-files.js',
'WebContent/resources/lib/angular-ui/ui-bootstrap-custom-tpls-0.14.1.min.js',
'WebContent/resources/lib/ng-table/ng-table.min.js',
'WebContent/resources/lib/websockify/util.js', 'WebContent/resources/lib/websockify/base64.js', 'WebContent/resources/lib/websockify/websock.js',
'WebContent/resources/lib/file-upload/ng-file-upload.min.js',
'WebContent/resources/js/services/*',
'WebContent/resources/js/services/dialogs/*',
'WebContent/resources/js/controllers/*',
'WebContent/resources/js/directives/*',
'WebContent/resources/plugins/*'],
dest: 'dist/myWebAppInOneFile.js',
},
},
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
Then just call grunt from the relevant folder and you'll get your file
What build toolchain are you using. One option would be to concatenate all of the includes into a single file, this should stop the error where the wrong scripts are being loaded - As mentioned by Marcus H
Gulp
https://github.com/contra/gulp-concat
Grunt
https://github.com/gruntjs/grunt-contrib-concat
I have download the sample https://github.com/tastejs/todomvc/tree/master/examples/typescript-angular and I try to get it working under a VS2013 Web Application empty template.
I add all the file of the sample, I launch the website by IIS, it works fine.
But when I build the project (without modifying anything) the only lines that remain are :
/// <reference path='_all.ts' />
/**
* The main TodoMVC app module.
*
* #type {angular.Module}
*/
var todos;
(function (todos) {
'use strict';
var todomvc = angular.module('todomvc', []).controller('todoCtrl', todos.TodoCtrl).directive('todoBlur', todos.todoBlur).directive('todoFocus', todos.todoFocus).service('todoStorage', todos.TodoStorage);
})(todos || (todos = {}));
When I try to run the website I have the following error :
http://localhost/WebAppTodoMvc/bower_components/angular/angular.js
0x800a139e - Erreur d’exécution JavaScript: [$injector:modulerr] Failed to instantiate module todomvc due to
Error: [ng:areq] Argument 'directiveFactory' is required
That code is meant to work with the --out compiler flag and you should use _all.js generated from all.ts https://github.com/tastejs/todomvc/blob/master/examples/typescript-angular/js/_all.ts
You can specify this as the reference file from your project properties.