How to use stomp with angular 1.5/es6 and webpack - angularjs

I am struggling to include stomp in my project. With both versions jmesnil/stomp-websocket or the subspequent forkJSteunou/webstomp-client.
I tried to import properly:
import Stomp from 'stompjs';//or 'webstomp-client';
import SockJS from 'sockjs-client';
and to load it like:
angular.module('app', [
uiRouter, ngTranslate, ngTranslateStaticFilesLoader, ngResource, ngFilter,
uiBootstrap, Stomp, SockJS
])
But I get the following error (with both versions):
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module {"VERSIONS":{"V1_0":"1.0","V1_1":"1.1","V1_2":"1.2"}} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object
(Even if webstomp.js has "function webpackUniversalModuleDefinition(root, factory) " on top, which apparently is not fullfilling its purpose)
It is possible to bypass this errors by importing it "wildly" directly on top the controllers where used, but then all karma tests are not running (error is : Error: Cannot find module "net"), even though node: { net: 'empty', tls: 'empty', dns: 'empty' } is added to webpack.config.js.
At this point anything I am trying just feels like weird black magic.
Is there a "constellation" of lib versions, angular wrappers, etc that is know to work properly with my setup (angular 1.5 / es6 / webpack 1.14 / karma) ?

Do not add it as a dependency to your angular module. The Stomp library is not an angular module. There might be a bridge available, but I don't think it is necessary.
To use Stomp with Webpack 2, simple require it at the tomp of the file where you are using Stomp and then use it as if it was a global variable.
const Stomp = require("stompjs/lib/stomp.js").Stomp;
Inside your controller/service:
Stomp.client(...);
Edit
This solution will be a bit more difficult to unit test, because you will not be able to replace the dependency easily the "angular way". To solve that issue, you might define it in your main module file as a constant and than use the DI provided by AngularJS.
Main Module File
const Stomp = require("stompjs/lib/stomp.js").Stomp;
angular
.module('app', [
// dependencies
])
.constant('Stomp', Stomp)
// other controllers/services/etc.
Controller/Service
function MyController(Stomp) {
Stomp.client(...);
}

Related

Use Strict Annotation Mode to Find Minification Bugs -- $injector:unpr Unknown provider

Why am I getting an "Unknown provider: e" error when hosting a production version of an Angular 7/AngularJS hybrid app in IIS?
I have an Angular 7/AngularJS hybrid app that I'm running. Everything runs fine in development mode using "npm start". However, after building a production version, the page gives me a
[$injector:unpr] Unknown provider: e
error. I've tried only running the Angular 7 code and that works fine. I've tried debugging and my angularjs code in an app.js file is being executed fine. The error seems to be coming from my app.module.ts when the code
this.upgrade.bootstrap(document.documentElement, ['app'], { strictDi: false })"
is executed.
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
ngDoBootstrap() {
this.upgrade.bootstrap(document.documentElement, ['app'], { strictDi: false });
}
}
declare var angular: any;
angular
.module("app")
.directive("example", downgradeComponent({ component: ExampleComponent }) as angular.IDirectiveFactory);
Not sure why I only get this error in production mode. I've deployed the app as an application in IIS. Any help would be appreciated. Thanks.
Use Strict Annotation Mode to Find Minification Bugs
angular.bootstrap(element, ['app'], { strictDi: false })
From the Docs:
strictDi - disable automatic function annotation for the application. This is meant to assist in finding bugs which break minified code. Defaults to false.
— AngularJS angular.bootstrap API Reference
How to Enable Strict Annotation Mode from HTML
<body ng-app="app" ng-strict-di="true">
<!-- ... -->
</body>
From the Docs:
ngStrictDi (optional) boolean
if this attribute is present on the app element, the injector will be created in "strict-di" mode. This means that the application will fail to invoke functions which do not use explicit function annotation (and are thus unsuitable for minification), as described in the Dependency Injection guide, and useful debugging info will assist in tracking down the root of these bugs.
— AngularJS ng-app Directive API Reference
For additional information, see
AngularJS Developer Guide - Using Strict Dependency Injection
On your angular.json, look at your "production" object. There might be a buildOptimizer or aot setting that might be generating an issue with the transpiled .js. I believe that the code is expecting the minified variable ("e") but at the moment of execution, the code hasn't been minified.

Unable to repro unavailable Angular Module error

Following is how my controller in Angular 1.x looks like -
const app = angular.module("userRegistration", [
"some-dep",
"templates",
"ngRoute",
"ngResource",
"ngCookies",
"userRegistration.controllers",
"userRegistration.services",
"userRegistration.directives"
]);
Everything runs fine but once in a while, the following error surfaces, mostly on a windows machine with Chrome browser version >= 62 -
Uncaught Error: [$injector:modulerr] Failed to instantiate module userRegistration due to: Error: [$injector:nomod] Module 'userRegistration' 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.
I came to know from another SO post that the issue lies in the syntax. The correct syntax is
var app = angular.module("MesaViewer", []);
But I am not sure why this error never sprang up in past. I tried to repro the issue on the same chrome browser version but was unable to.
Can you pls try this..
const app = angular.module("userRegistration", [
"some-dep",
"templates",
"ngRoute",
"ngResource",
"ngCookies"
]);
There is not need to inject the controller, services, etc from the same module

angular webpack ng-file-upload

I'm trying to get ng-file-upload to work with my angularjs project, which uses webpack. I installed ng-file-upload via npm and added it to my main app.js
var ngFileUpload = require('../../node_modules/ng-file-upload/dist/ng-file-upload.min');
module.exports = angular.module('app', [ngFileUpload])
But I'm still getting:
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module {} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object
Could anyone tell me what I'm doing wrong, since I tried to find any information about this with no success.
Look for what ngFileUpload is exporting and what's the name of module. Right now you are injecting the module inside angular dependency but you need to just give name of your ngFileUpload module not the ngFileUpload it self. That's why you are getting this error. It's expecting a name of module but getting a object instead.

Angular 1.5 and ES6 - importing module

I'm trying to get my head around using the new capabilities in Angular 1.5 and also using Webpack and ES6 via Babel.
In one case, I want to bring in a module (ngStorage), but ngStorage is written in classic 1.x style. So this file:
import angular from 'angular';
import ngStorage from 'ngstorage';
import UserSettings from './user-settings';
import UserFactory from './user.factory';
let userModule = angular.module('user', [ngStorage])
.service('UserSettings', UserSettings)
.factory('User', UserFactory);
export default userModule;
results in this error at runtime:
Error: [$injector:modulerr] Failed to instantiate module user due to:
Error: [$injector:modulerr] Failed to instantiate module {"_invokeQueue":[["$provide","provider",{"0":"$localStorage"}],["$provide","provider",{"0":"$sessionStorage"}]],"_configBlocks":[],"_runBlocks":[],"requires":[],"name":"ngStorage"} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object
I'm guessing that I just can't import from ngstorage - it doesn't export anything. Is there a way I can shim 1.x dependencies in order to import them?

ADAL library gets mangled when used with SystemJS loader - ReferenceError: AuthenticationContext is not defined

I built a small test application using Angular1 that uses ADAL to connect to an Office365 tenant. Since I wish to start including Angular2 components, I tried to use JSPM and SystemJS to load my modules, as per the examples on angular.io.
I am putting the information below for anyone who stumbles on the same error message:
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
ReferenceError: AuthenticationContext is not defined
It took me literally hours to figure out what was wrong, stepping blindly through ADAL code. The ADAL.js file relies on the fact that it declares AuthenticationContext in the global namespace, and using SystemJS packages it when it loads the file into a "module" which now hides it from the other piece of code that relies on it.
I guess Microsoft can do a better job packaging its code - ideally make it an NPM package (instead of just supporting Bower), but I don't really know how this can be solved...
To obtain the files, I used jspm commands such as:
jspm install angular
jspm install github:azuread/azure-activedirectory-library-for-js
that cleanly populated my package.json with the proper dependencies, allowing installation on another dev machine easily.
When I use the Microsoft supplied examples, they simply statically load the javascript files using script tags in the HTML. SystemJS makes it a whole lot simpler in both development and production, since it loads dynamically at run time. However, when I rely on the import statements in my main app code below, SystemJS seems to wrap the code in adal.js inside a "module", so it effectively hides variables that used to exist in the global scope. This result in an error because the variable AuthenticationContext is then undefined globally.
My main app code looks like:
import 'angular';
import 'azuread/azure-activedirectory-library-for-js/dist/adal.min';
import 'azuread/azure-activedirectory-library-for-js/dist/adal-angular.min';
var app = angular.module('app', ['AdalAngular']);
app.config(
['$httpProvider', 'adalAuthenticationServiceProvider', function
( $httpProvider, adalProvider) {
var endpoints = {
"https://login.microsoftonline.com": "56fc9778-8aac-45d2-9305-b9171ffafa8/oauth2/authorize"
};
adalProvider.init(
{
tenant: '56fc9778-8aac-45d2-9305-b9171ffafa8',
clientId: 'ace0c960-c792-4620-884e-9029ba16b61',
endpoints: endpoints
},
$httpProvider
);
}]);
export {app};
My fix is simply to comment out the second line in my code:
//import 'azuread/azure-activedirectory-library-for-js/dist/adal.min';
and to get the code, I just need to manually load it using a script tag in my index.html file that refers to the CDN supplied by Microsoft
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/adal.min.js"></script>
This is not super clean, but it works.
You should just be able to export adal as AuthenticationContext. I've tested the following systemjs config and it works for me.
meta: {
'node_modules/angular/angular.js': { format: 'global', exports: 'angular' },
'node_modules/adal-angular/dist/adal.min.js': { format: 'global', exports: 'AuthenticationContext' },
'node_modules/adal-angular/dist/adal-angular.min.js': { format: 'global', deps: ['angular', 'adal'] }
},
paths: {
'angular': 'node_modules/angular/angular.js',
'adal': 'node_modules/adal-angular/dist/adal.min.js',
'adal-angular': 'node_modules/adal-angular/dist/adal-angular.min.js'
}
You can then just import 'adal-angular'; and AuthenticationContext should be available.

Resources