Class constructor UpgradeComponent cannot be invoked without 'new' after Update to Angular 10 - angularjs

I just started to upgrade an Angular project from 9.1.0 to 10.0.12
It is still a hybrid app and has couple of components upgraded (from Angular JS) as described in the Angular docs
However after the Update to Angular 10 those upgraded components would not load and result in the following error
Class constructor UpgradeComponent cannot be invoked without 'new' (at new MyUpgradedComponentDirective)
I searched the Changelog and didn't found any information regarding UpgradeComponent.

Changing jit to true might be not the best solution - that will switch the directive to the mode, when it's compiled in browser runtime, instead of being served as pre-compiled JS code.
It seems like the issue described here might be solved with setting tsconfig.json output property to ES2015 if you have older version there.
More details can be found here: https://github.com/angular/angular-cli/issues/18067

After endless search without results I went to trial & error mode.
I discovered that there is a jit property on the #Directive, if set to true the mentioned error goes away.
With adding jit: true the upgraded component code looks something like this
#Directive({
selector: 'my-angular-selector',
jit: true,
})
export class MyDirective extends UpgradeComponent {
constructor(elementRef: ElementRef, injector: Injector) {
super('angularJsDirectiveSelector', elementRef, injector);
}
}

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.

Downgrade Angular route component

Bit of an odd question. I have a massive AngularJS directive that should be entirely re-written. The challenge is too great to do it all at once. I was wondering if there is a way to downgrade a route component in AngularX to load in this AngularJS directive without refactoring it yet. I cannot find any details on this.
Downgrading the angular component allows me to use something called projections which is the equivelant to AngularJS' transclusion.
I have tried many approaches, but my best shot was the following:
// component
#Component({
selector: "some-component",
templateUrl: "./some.component.html",
})
export class SomeComponent{}
// routes
{ path: "some-route", component: SomeComponent}
// downgrades
import { downgradeComponent } from "#angular/upgrade/static";
import {SomeComponent} from "./some-location"
angular.module("somemodule").directive(
"someComponent",
downgradeComponent({ component: SomeComponent })
)
So far no luck. Since the Application is pretty big. This would make perfect little commits to work towards a migrated system. If the names do not match. The application will break because it cannot find the directive name.
If the downgrade worked, one would expect angularjs components to work on the route.
After some more digging, this would never work. I ended up just upgrading the directive using the UpgradeComponent class: https://angular.io/api/upgrade/static/UpgradeComponent
downside is that it added a lot of boilerplate by creating a wrapper.

Setting up Angular for production

I have been trying to follow the suggestions for running an angular app in production. However I have been struggling to disable the comment and css class directives:
$compileProvider.commentDirectivesEnabled(false);
$compileProvider.cssClassDirectivesEnabled(false);
When I try to add these commands to the config block I receive the error:
$compileProvider.commentDirectivesEnabled is not a function
The codepen below demonstrates my issue, if you comment out the two lines then the code runs without any problem:
http://codepen.io/anon/pen/RoaKbj?editors=1010
These two methods don't exist in the 1.5.8 version of angular that you're using.
They exist in the 1.6.0-rc.0 version though.

How to debug typescript in angular-meteor

I followed the angular-meteor tutorial for the Socially app in Angular2. It basically works (after a few manual steps to fix package dependencies, etc), however, I am unable to debug the client side code in Chrome Dev Tools. When I navigate to the sources for my *.ts files, all I see are things like
module.export("default",exports.default=("<div> <ul> <li *ngFor=\"let party of parties\"> {{party.name}} <p>{{party.description}}</p> <p>{{party.location}}</p> </li> </ul> </div>"));
Other strange things in dev tools: my app.ts is blank. I see html files with !raw suffixes.... (e.g. app.html!raw). What is the !raw suffix and what causes that?
How can I debug my typescript?
I may be able to help with some parts of your question.
You don't mention which version of meteor you're using, but I assume version 1.4 or 1.4.0.1. I have seen that these versions of Meteor seem to have issues with sourcemaps for Typescript files (probably as they have to go through multiple transpilation steps).
I don't yet know where exactly the bug lies (Meteor or the Typescript compiler package).
Here's one github issue for this: https://github.com/barbatus/typescript/issues/23
UPDATE: This issue has now been fixed.
For now, my suggestion would be to try reverting to a 1.3.x.x version of Meteor. For something like the Socially tutorial, the easiest option is to specify the Meteor release at creation time:
$ meteor create --release 1.3.5.1 Socially
(list of releases is at: https://github.com/meteor/meteor/releases)
The 'app.html' and 'app.html!raw' files are generated by the meteor angular compilers as a way of working around issues with using templateUrl and the meteor build process. My understanding is that the preferred approach is to have inline templates or import the templates like this:
// This import loads the content of the html file into 'template'
import template from './app.html';
#Component({
selector: 'app',
// Instead of templateUrl, use:
template, // <--- 'template,' is syntactic sugar for: 'template: template,'
directives ... etc.
The import statement is a bit unusual, and this magic is achieved by the meteor angular pre-compiler that converts every html and css file into a couple of js files. That's what strange app.html and app.html!raw are.
The funny characters in the first app folder seem to be a bug. Meteor tries to generate put in a computer emoji, but sometimes this gets handled incorrectly. I'm not sure if this is a bug Chrome, ChromeDevTools or Meteor. (Personally, I wish they'd ditch the emoji).

react-css-modules with decorators not working

Trying to get decorator syntax working for react css modules as shown here.
https://github.com/gajus/react-css-modules#decorator
I've got react-css-modules working using the function syntax, e.g.
CSSModules(Table, styles)
but when using decorators, e.g.
#CSSModules(styles)
export default class extends React.Component {}
nothing seems to be instantiated and no errors are thrown either. I've got the babel-plugin-syntax-decorators loaded.
What could I be missing? Thanks!!
I wasn't able to use that syntax too. It seems that react-scripts uses some babel plugin for running typescript, and that plugin isn't much typescript. So if you're using react-scripts with typescript, consider that it's not "full" typescript, and there is some stuff not working as you could expect.
Also, you can consider using patch-styles instead of react-css-modules. It's much simpler, doesn't require any changes in your project at all, and PatchStyles provides the same with a lot simpler react component.

Resources