DefinitelyTyped: What does 'export = _;' means - angularjs

I'm trying to use angular-material with a ng-metadata project and I run into some issues.
I use DefinitelyTyped for angular material and the first lines are:
declare module 'angular-material' {
var _: string;
export = _;
}
In my main.ts I try to import { ngMaterial } from 'angular-material';
then bootstrap( AppComponent, [ 'ngMaterial' ] ); but all I got is:
Error:(3, 10) TS2305: Module ''angular-material'' has no exported member 'ngMaterial'.
I don't know what I am doing wrong

When being used through ES6 or TypeScript, a common pattern that Angular modules follow is that they'll use their name as the default export. For example, one of the modules in my application looks like this:
const session = angular.module("smSession", [])
.service("session", SessionService)
.component("smLogin", Login)
.config(routes)
.run(loginRedirect);
export default session.name;
The reasoning behind this is that it makes the syntax for declaring an Angular module's dependencies cleaner; for example:
import angular from "angular";
import ngAnimate from "angular-animate";
import ngMaterial from "angular-material";
import uiRouter from "angular-ui-router";
let module = angular.module("myApp", [ ngAnimate, ngMaterial, uiRouter ]);
If they instead exported the entire module, you'd have to do this:
let module = angular.module("myApp", [ ngAnimate.name, ngMaterial.name, uiRouter.name ]);
So this is why the main module declaration for angular-material looks like it does - they're simply representing the fact that all you can import from the package is that one string representing the module's name. The rest of the type definitions are ambient - you can just use the angular.material namespace anywhere in your application without having to do an import.
EDIT: To clarify, here's the actual source of the file that gets imported when you import ngMaterial:
// Should already be required, here for clarity
require('angular');
// Load Angular and dependent libs
require('angular-animate');
require('angular-aria');
// Now load Angular Material
require('./angular-material');
// Export namespace
module.exports = 'ngMaterial';
Notice that require('./angular-material') doesn't return anything - that import effectively just runs the file that sets up the Angular module behind the scenes (effectively the same sort of code as in my examples). The only thing being exported from the module is the name.

Related

Error when importing UpgradeAdapter to upgrade to Angular 4 (import declaration can only be used in a namespace or module)

I'm starting to upgrade an AngularJS app to Angular 4, and I'm trying to bootstrap it using the upgrade adapter like this in the ('entry' file for the app) - where the function is within a closure, in an independent app.ts file :
app.ts (was previously App.js):
(function () {
import { UpgradeAdapter } from '#angular/upgrade';
var adapter = new UpgradeAdapter();
adapter.bootstrap(document.body, ['portalHomeApp']);
angular
.module('portalHomeApp', ['shared']);
I'm getting an error for the initial import of UpgradeAdapter:
An import declaration can only be used in a namespace or module
What do I need to do? Do I somehow make it available to the 'portalHomeApp' module, or do I simply now need a namespace now that I'm using TypeScript?

No provider for $scope! error when using a angular 1 directive in an angular 2 app

I have an angular 2 App built with angular-cli and I need to use an angular 1 directive in one of my components (to re-use it from a different application). I followed the steps from:
https://angular.io/docs/ts/latest/guide/upgrade.html#!#using-angular-1-component-directives-from-angular-2-code
But now I got to this error and cannot get past it. I am using angular2.0.2 (I managed to build a hybrid app in the past with the beta version but it was an angular1 app and I used angular 2 components with downgrade function of the adapter).
In my app.module.ts I have:
import { UpgradeAdapter } from '#angular/upgrade';
const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
#NgModule({
imports: [
BrowserModule,
...
],
declarations: [
...
HeroDetail
]
})
export class AppModule { }
and my hero-detail.component.ts looks like this:
export const heroDetail = {
templateUrl: 'hero-detail.html',
controller: function() {
}
};
and my hero-detail.html looks like this:
<h2>Windstorm details!</h2>
I try to use the directive in another angular 2 component simply by adding in the template:
When I run ng serve, the application compiles fine but when I try to load the page I get the mentioned error.
Any suggestions on how I can move forward with this?
It seems you have incorrect bootstrap logic.
It's actually not quite obvious, make sure that:
you don't bootstrap any ng2 component with #NgModule({bootstrap:[ ... ]}). Instead, you should have empty ngDoBootstrap() { } method in your main module.
root template is ng1 template. I.e. in your index.html you should have only ng1 components or downgraded ng2 components. You can have ng2 component as a root, but you need to downgrade it first.
Official upgrade guide contains an example of DOM structure:
... which ensures that ng2 injectors have all required providers from ng1.

Angular modules import with webpack - Argument 'module' is not a function, got Object

I've been trying to setup angular 1 with webpack and ran into an issue with import modules, let's say I want to import ramda from node_modules
import angular from 'angular';
import uirouter form 'angular-ui-router';
import routing from './app.config';
import * as ramda from 'ramda';
angular.module('app', [uirouter, ramda])
.config(routing);
I get an error: Argument 'module' is not a function, got Object. If I console ramda, it is indeed an object and I understand I need a string, but I just couldn't figure out how to get it?
Change it to import ramda from"ramda".
This is because the export of the module is the module name.
When you write import * as ramda you import the namespace object, which is an object containing all the exports of that module.
If you are using TypeScript, you may need to add a allowSyntheticDefaultImports to your tsconfig.json.
allowSyntheticDefaultImports

'smth' is already declared in the upper scope

I am using some starter kit for angular. There are webpack, eslint and other useful things.
But, I don't understand how to works with dependency. I have the following code:
import angular from 'angular';
import routing from './app.config';
import auth0 from 'auth0-js';
import jwtHelper from 'angular-jwt';
import store from 'angular-storage';
...
angular.module('app', [
uirouter,
...
jwtHelper,
store,
...
])
.config(routing)
.run(($state, auth, store, jwtHelper) => {
some code;
});
But, I get the following errors:
99:16 error 'auth' is already declared in the upper scope no-shadow
99:22 error 'store' is already declared in the upper scope no-shadow
99:29 error 'jwtHelper' is already declared in the upper scope no-shadow
Hot to use them properly?
Simply rename one of the duplicated declared variable so that your scope doesn't clutter.
You can either rename the upper part
import angularJwt from 'angular-jwt';
import angularStorage from 'angular-storage';
or simply rename the dependencies like: (and keep the original names in the $inject declaration)
routing.$inject = ['$urlRouterProvider', '$locationProvider', 'localStorageServiceProvider'];
export default function routing($urlRouterProviderCustomName, $locationProviderCustomName, localStorageServiceProviderCustomName) {
$locationProviderCustomName.html5Mode(true);
$urlRouterProviderCustomName.otherwise('/dash');
localStorageServiceProviderCustomName.setPrefix('elmahbucket');
}

angular-moment is not loaded by angular in meteor app

I do tutorial from angular-meteor.com. angular-moment worked well. Then I added some Ionic elements to html page and empty stub method to controller. And got the message:
13:07:29.038 Error: [$injector:modulerr] Failed to instantiate module
Whatsapp due to: [$injector:modulerr] Failed to instantiate module
angular-moment due to: [$injector:nomod] Module 'angular-moment' 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.
http://errors.angularjs.org/1.5.3/$injector/nomod?p0=angular-moment
minErr/<#http://localhost:3000/packages/modules.js?hash=a65f000925e20c56ee4ab84205897b99db3e2c9f:232:12
module/<#http://localhost:3000/packages/modules.js?hash=a65f000925e20c56ee4ab84205897b99db3e2c9f:2198:1
ensure#http://localhost:3000/packages/modules.js?hash=a65f000925e20c56ee4ab84205897b99db3e2c9f:2122:38
module#http://localhost:3000/packages/modules.js?hash=a65f000925e20c56ee4ab84205897b99db3e2c9f:2196:1
loadModules/<#http://localhost:3000/packages/modules.js?hash=a65f000925e20c56ee4ab84205897b99db3e2c9f:4688:22
forEach#http://localhost:3000/packages/modules.js?has minErr/<()
modules.js:232 loadModules/<() modules.js:4711 forEach()
modules.js:485 loadModules() modules.js:4672 createInjector()
modules.js:4594 bootstrap/doBootstrap() modules.js:1874 bootstrap()
modules.js:1895 onReady() app.js:100
require<.node_modules.meteor.jquery["jquery.js"]/
I rolled back my changes, by commenting them out, but still have this error.
UPDATE
The following code causes error:
import angular from 'angular';
import 'angular-animate';
import 'angular-meteor';
import 'angular-moment';
import 'angular-sanitize';
import 'angular-ui-router';
import 'ionic-scripts';
// Modules
import Definer from '../definer';
import ChatsCtrl from '../controllers/chats.controller';
import ChatCtrl from '../controllers/chat.controller';
import CalendarFilter from '../filters/calendar.filter';
import RoutesConfig from '../routes';
// App
const App = angular.module('Whatsapp', [
'angular-meteor',
'angular-moment',
'ionic'
]);
Module angular-moment was installed as follows:
>meteor npm install --save angular-moment
angular-moment#1.0.0-beta.5 node_modules/angular-moment
└── moment#2.12.0
Clever... Documentation says it must be named angularMoment.. Very nice.
var myapp = angular.module('myapp', ['angularMoment']);
There is a mistake in tutorial. As for me, naming module in such a way makes coding more error-prone, because import is makes for angular-moment, but anlike others modules, it name is another.

Resources