Hybrid angular app throwing error "'./app.module.ajs.js' does not provide an export named 'default'" - angularjs

I am attempting to convert my AngularJS project to run as a hybrid (i.e. 1.x alongside 2+) following the bootstrapping steps provided at the angular.io guide page provided specifically for the task. I have followed the guide with some modifications (primarily just so that I could maintain my existing project structure). My steps in inexact order have been to
include webpack
convert my original app.module.js and all angular modules declared therein to exportable ES modules
(app.module.js became app.module.ajs.ts, which is transpiled to .js)
add a new app.module.ts for manual bootstrapping, as per the docs (looks identical to the file of the same name in the docs) and remove the ng-app directive from the html as it is no longer necessary
import the modules into all dependent controller, direcive and service files.
Now when I serve the project, which I believe is the step I should be on (the steps seemed pretty straightforward...) I get a slew of the same error:
However when I open that file up, I do actually see exports.default = ariaApp.
Also, the .ts file by the same name does indeed contain the declaration and the default export
const ariaApp = angular.module("ariaApp", [])
export default ariaApp;
Has anyone seen this before? / Does anyone know what this error indicates? It seems totally off... All suggestions appreciated! Thank you!!

Related

Converting to TypeScript files for AngularJS app

I have a large AngularJS app which I am in the process of upgrading (with NgUpgrade, webpack etc.) To start with, my new Angular (4) components are .ts files but my old AngularJS parts are .js files, transpiled using the Babel loader for webpack.
I would like to migrate all .js files to .ts files so that I can have everything go through the TypeScript compiler and no longer require Babel etc.
For the most part, the app runs fine (with a few small tweaks) by just renaming the files from .js to .ts and adding an import for angular at the top:
import * as angular from 'angular';
However, when I run my app, I now see a warning:
WARNING: Tried to load angular more than once.
This makes sense because Angular would be loaded once by the global script include, and once by the module import.
I can't avoid having the global script include, because I am using other scripts that require the angular global variable to be present.
As such, I think I should be using the global variable, but need to declare it to keep the TypeScript compiler happy (as per NgUpgrade documentation). I have tried changing the top of each file to:
declare var angular: angular.IAngularStatic;
This doesn't work and I get an error like the following:
TS2503: Cannot find namespace 'angular'.
Can anyone please tell me what is going wrong? I have installed #types/angular with npm/yarn and do not have typeRoots or types in my tsconfig.json file. My understanding is that this should automatically find the declarations in node_modules/#types but this doesn't seem to be the case?
I've found a solution which is working nicely (thanks to https://stackoverflow.com/a/42035067/1145963).
Added a .d.ts file at the root of my project:
declare global {
const angular: ng.IAngularStatic;
}
export {};
This allows me to use the angular global from anywhere, without needing any import or declare statements at the top of the files and without needing to do any special Webpack configuration.

Questions regarding Angular 2 files

Could someone help a newbee. I just went through the Angular.io quickstart.
I finally got the project to run but the following questions came up.
First: These points the quickstart guide stated that App.module.ts is the app entry point. That it consumes the component app.component.ts and that main.ts initializes the platform that your app runs in. Also, there's index.html.
So in plain English is this correct.
App.module.ts (Is this like the main of the program)
app.component.ts (Is a module that app.module.ts consumes).
(main.ts) Initializes the nodejs platform (I am assuming that means gets the environment that Javascript run in ready on your pc.)
index.html (is the start web page)
Also, do you always start every app with Index.html as the main starting web page for Angular 2 apps?
Thanks in advance.
App.module.ts (Is this like the main of the program)
This is the module you use to bootstrap/setup your main module and declare app dependencies such as ngMaterial
app.component.ts (Is a module that app.module.ts consumes).
This is the module you would use to create routes to link to other modules and be the base module
(main.ts) Initializes the nodejs platform (I am assuming that means gets the environment that Javascript run in ready on your pc.)
This is the main entry module and here you can swap out the JiT (Just in Time) compiler for an AoT (Ahead of Time) compilation to make the app even more skinny
index.html (is the start web page)
This is just the file which includes the correct js files, this could be called anything
Hope that helps I am still learning myself so if anything is wrong please point them out so I can alter it and learn.

Angular - umd.js vs rx.umd.js

Following Angular tutorial, one can see:
<script src="node_modules/angular2/bundles/angular2.umd.js"></script>
used in https://angular.io/docs/js/latest/guide/forms.html while,
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
used in https://angular.io/docs/js/latest/quickstart.html
Can someone please explain or point to a document that explains when to invoke which JS file. Thanks in advance
The UMD bundles are intended for users who write in ES5 and for those users interested in ngUpgrade.
There's a file called overview.md located at https://code.angularjs.org/2.0.0-beta.0/, you can check over there what's its purpose. This file is not yet part of http://angular.io but it's most likely to be included in a future.
Quoting part of that document
ES5 and ngUpgrade users
ES5 users and AngularJS 1.x users interested in the ngUpgrade path can take advantage of the bundles in the UMD format.
Those are coarse-grained bundles that combine many barrels in one final file.
Warning: bundles in the UMD format are not "additive". A single application should use only one bundle from the above list.
In your case you would need Rx.umd.js (or the minified version if you want) and ONE of the Angular2 UMD bundles.
In the document itself there's a list/table of what contains each one.
Update
The overview file, while it's not yet available in the website can be found in the repository. Check overview.md.

Webpack with angular 1.x and ES5

After reading hundreds of lines about browserify vs webpack and several how to of both I decided to go for webpack. The main reason it's because I liked the idea of bundling everything into a js file.
I have an angular project already working and I want to refactor it for webpack. The problem? My project is using angular 1.4.7, ng-animate and plain javascript (ES5) and all the tutorials and manuals are for ES6. I don't want to refactor my project so much. What's the way to go? I would like an example of each angular module : factory, directive, controller and so on. Many thanks
I typically have a feature.module.js file which has my module definition and requires all of the directives / services contained within the module. Also has the external dependancies.
/* module.js */
angular.module('my.module',['dependancy1', 'dependancy2']);
//External libraries
require('./dependancy1.module.js');
require('./dependancy2.module.js');
//Internal components
require('./thing.directive');
require('./thing.service';
/* service.js */
angular.module('my.module')
.directive('yourDir', function myDir(){...});
I'm dealing with the same problem now. And I found something that works (work in progress, but at least I can see progress). My steps:
Install yeoman
Run this angular-webpack generator. Select 'ES5' when asked (the other option is 'ES2015', which I guess is the same that 'ES6')
Start modifying the automatically generated boilerplate with your Angular code
Yes, you still need to learn about gulp and sass, but at least you can run a simple AngularJS app using the old ES5 syntax, and start modifying it.
I'm probably blogging about this. So, I'll update this answer then.
I tend to do this:
app.js:
require('/any/angular/deps');
var subModule = require('/some/sub/module');
var app = angular.module('myApp', []);
// pass the app module in sub modules to allow them to define their own config
subModule.configure(app);
/subModule/module.js:
var someSubDirective = require('./subDir/directive');
export function configure(app) {
someSubDirective.configure(app);
}
/subModule/subDir/directive.js:
export function configure(app) {
app.directive('myDir', myDir);
}
function myDir() {
}
My idea is to let all sub modules handle their own configuration, so declaring config or constant, factories or providers. Letting this then bubble up to the app.js. This means its really easy to delete a folder from your structure, because it is one line removal from it's parent module.
This also makes relevant file paths a lot shorter and easier to handle.

How to independence inject Browserify Crypto in Angular Ionic

I new bee of Ionic and angular. I used Browserify to require Crypto module of nodejs for my Ionic project. Following are my steps:
I added new line to app.js file
angular.module(.....).constant('Crypto',require('crypto'))
I run the command line, which create new file perfectly with code of Crypto module and app.js file
browserify app.js > bundle.js
I replace app.js by bundle.js in index.html file
I try to test it in service.js
angular.module('mapp.services').factory('abc',['$http','Crypto',function($http,Crypto){
return {
getAllProduct:function(){ console.log(Crypto.SHA256("Message"));
});
} }]);
It return message "Crypto.SHA256 is not a function". I think that "constant" means a value, not a static object, so that I cannot pass Crypto to "constant". So, how can I require all needed modules at app.js file by Browserify and then pass use it at other js file, like $http?
Thanks!
Sorry because of my stupid question. The fact that we can assign Crypto object to constant pool. The problem is my code. To encrypt a string, the code must be
crypto.createHash('sha256').update(mystr).digest('base64');
instead of
crypto.sha256(mystr)
Now problem solved, but thanks for your all reply and comments.
I don't think Crypto will work on the client, it's the server-side library for performing encryption and is largely a wrapper around OpenSSL (see here).
The functions that it wraps cannot be called in Ionic/Angular for the simple reason that they aren't available on the client.
Try using CryptoJS instead as was proposed by this answer - it was designed to be used client-side like in your Ionic/Angular project to perform cryto-related operations.

Resources