1

I'm using ES5 flavor of Angular 2. Thus instead of using decorators, I define a template as follow:

var someComponent = ng.core.Component({
    // component configuration
}).Class({
    // component class
});

It was working fine. Recently I upgraded to Angular 5, and now I have these error for the same code:

ng.core.Pipe(...).Class is not a function
ng.core.Component(...).Class> is not a function
ng.core.Directive(...).Class is not a function

How should I change this in Angular 5?

  • Totally unrelated, but can u pls tell me why did u choose to use ES5 over tyescript ? – Dhyey Jan 05 '18 at 06:45
  • @Dhyey, why unrelated? The reason we had to use ES5 is because we're using Angular inside a corporate architecture that enforces many more things which are not supported in Angular. For example, there is no way to use one json configuration across many Angular projects. – mohammad rostami siahgeli Jan 05 '18 at 06:59

1 Answers1

4

JavaScript is currently considered second-class (no pun) citizen, while TypeScript is the language of choice, primarily because of the focus on AOT compilation, which is available for TypeScript only.

As explained here,

It is no longer possible to declare classes in this format.

Component({...}).
Class({
  constructor: function() {...}
})

This format would only work with JIT and with ES5. This mode doesn’t allow build tools like Webpack to process and optimize the code, which results in prohibitively large bundles. We are removing this API because we are trying to ensure that everyone is on the fast path by default, and it is not possible to get on the fast path using the ES5 DSL. The replacement is to use TypeScript and @Decorator format.

@Component({...})
class {
  constructor() {...}
}

As described in this answer, the alternative to decorators in plain ES5 and higher is the annotation of classes (and therefore, functions) with annotations and parameters static properties.

So

var SomeComponent = ng.core.Component({...})
.Class({
  constructor: [
    [new ng.core.Inject(Svc)],
    function (svc) {...}
  ],
  foo: function () {...}
});

becomes

SomeComponent.annotations = [new ng.core.Component(...)];
SomeComponent.parameters = [
  [new ng.core.Inject(Svc)]
];
function SomeComponent(svc) {...}
SomeComponent.prototype.foo = function () {...};

As a replacement for Class functionality, any third-party utility class library can be used to introduce syntactic sugar and inheritance in ES5 as a substitute for functions, e.g. uberproto or inherits.

It it highly advisable to migrate existing Angular JavaScript applications to TypeScript, the latter offers superior performance and much smaller application footprint in AOT compilation mode, which is going to be default mode in future versions.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • my personal experience is that Angular 2 is somehow frustrating for people who had some infrastructure before they come into its world, and its not mature at all for real-world corporate requirements. I've explained it [here](https://github.com/angular/angular/issues/21352). Based on your other answer I think you might also agree on that. – Saeed Neamati Jan 06 '18 at 05:29
  • @SaeedNeamati I'm not fond of some decisions made by the team, but most of the points you've listed may result from the lack of experience with Angular development (except the fact that Angular is opinionated and just isn't for everyone). A lot of infrastructure problems are supposed to be solved with Angular CLI and/or boilerplate repo. All a dev needs to do is to *fork* a starter and pull changes to keep the project in sync, no 'easily deviate' problem. – Estus Flask Jan 06 '18 at 13:26
  • *We don't want to create a module per component to load modules lazily* - extreme modularization was 'best practice' since A1. TS and imports are supposed to address a LOT of problems and human mistakes. You can keep several framework versions within same project. You can't do that in A1. Besides the fact that AOT couldn't work with raw ES5/ES6. AOT is flawed but it allows to keep the framework performance and footprint on par with React and Vue (more or less) - something that was a problem since A2 release and wouldn't be possible otherwise. Notice that both React and Vue are also compiled. – Estus Flask Jan 06 '18 at 13:50
  • @estus, `function SomeComponent() {...}` can't be used as a replacement for `.Class({...})`, because the `Class` gets a JSON object as the argument, and has constructor of course, but the `function` definition gets JavaScript as body. Can you guide me to a real example on that? – mohammad rostami siahgeli Jan 07 '18 at 13:53
  • @mohammadrostamisiahgeli The *result* of .Class(...) is a function. `.Class({ constructor: function () {/*init*/ }, foo: ...)` becomes `function SomeComponent() {/*init*/}; SomeComponent.prototype.foo = ...;` This isn't specific to Angular development. This is about how 'classes' are done in ES5. Have you checked ES5 and ES6 examples in linked answer? I believe it describes this in detail. – Estus Flask Jan 07 '18 at 14:52
  • I somehow can't understand it. I guess I have to go back to Angular 2. Shame that Angular guys are soooooooo opinionated that it prevents you from enjoying it in your own architecture. jQuery or Bootstrap are so flexible you can integrate them with almost any architecture out there. But Angular only works the way it works. – mohammad rostami siahgeli Jan 07 '18 at 15:40
  • Because jQuery and Bootstrap are libraries, and Angular is a framework. All modern frameworks are opinionated to some point. You can stick to A4 for now, it still got `Class`. – Estus Flask Jan 07 '18 at 16:03