If you have a variable called ws
of type WebSocket
, you can not assign null
or undefined
to that variable
In order to make a variable that is either of the given type or undefined
, use the following syntax:
ws?: WebSocket = undefined;
If you have a variable called ws
of type WebSocket
, you can not assign null
or undefined
to that variable
In order to make a variable that is either of the given type or undefined
, use the following syntax:
ws?: WebSocket = undefined;
In order to proxy /api
to http://localhost:62232
for example, first create proxy.conf.json
in the same directory where package.json
is located:
{ "/api": { "target": "http://localhost:62232", "secure": false } }
Now we need to modify package.json
. Locate the line where ng serve
is called, such as:
"start": "ng serve",
and add --proxy-config proxy.conf.json
to the arguments of ng serve
:
"start": "ng serve --proxy-config proxy.conf.json",
Full example for the scripts
section of package.json
:
"scripts": { "ng": "ng", "start": "ng serve --proxy-config proxy.conf.json", "build": "ng build --configuration=production", "watch": "ng build --watch --configuration development", "test": "ng test" },
For this route:
{path: 'my/:id', component: MyDashboardComponent},
this is how you can use it in MyDashboardComponent
:
constructor(private route: ActivatedRoute) { this.route.params.subscribe(params => { console.info(params.id); }) }
You have an Angular service implementing OnInit
:
import { Injectable, OnInit } from '@angular/core'; @Injectable() export class MyService implements OnInit { constructor() { } ngOnInit() { console.log("MyService initializing"); } }
but it never prints MyService initializing
– i.e. the ngOnInit()
function is never actually being called.
Services should not implement OnInit
, the function is deliberately never called. Instead, add the code from ngOnInit()
in the constructor()
and remove implements OnInit
and ngOnInit()
:
import { Injectable, OnInit } from '@angular/core'; @Injectable() export class MyService { constructor() { console.log("MyService initializing"); } }
You have angular HTTP client code like
this.http.get<MyType>(`${this.baseURL}/api/myAPI`).toPromise()
but toPromise()
is deprecated in recent versions of angular / rxjs.
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */ toPromise(): Promise<T | undefined>;
In most cases, for HttpClient, you want to use rxjs’s firstValueFrom()
since the HttpClient Observable
s typically only return one value anyway.
First, import firstValueFrom
from rxjs
:
import { firstValueFrom } from 'rxjs';
then remove the .toPromise()
call:
// Before this.http.get<MyType>(`${this.baseURL}/api/myAPI`).toPromise() // After this.http.get<MyType>(`${this.baseURL}/api/myAPI`)
and surround the entire statement with firstValueFrom
:
// Before this.http.get<MyType>(`${this.baseURL}/api/myAPI`) // After firstValueFrom(this.http.get<MyType>(`${this.baseURL}/api/myAPI`).toPromise())
This will fix the issue.
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { MyType } from './my-type'; @Injectable() export class MyService { baseURL = "http://localhost:18674"; // Replay subject: New subscribers will get previous values public nodes = new ReplaySubject<MyType>(); constructor(private http: HttpClient) { // Currently only acquire nodes once this.http.get<MyType>(`${this.baseURL}/api/myapi`).subscribe(value => this.values.next(value); }); } }
When trying to run a command like ng build
, e.g. in a CI setup, you see an error message like
sh: ng: not found
Only the machine where you’re running this command, you have not installed the ng
command globally.
However, your node_modules
folder will have a local installation of @angular/cli
.
In order to use it, replace ng
by ./node_modules/.bin/ng
.
For example, a scripts
section of your package.json
"scripts": { "build": "ng build" },
would be replaced by
"scripts": { "build": "./node_modules/.bin/ng build" },
Install ng
globally on the machine running the command by using
sudo npm i -g @angular/cli
ng build --prod --aot --build-optimizer --common-chunk --vendor-chunk --named-chunks
While it will consume quite some CPU and RAM during the build, it will produce a highly efficient compiled output.
You are trying to compile your Angular 9.x application, but you see an error message like
app/my-component/my-component.component.ts:24:4 - error TS2554: Expected 2 arguments, but got 1. 24 @ViewChild(MyOtherComponent) myOtherComponent: MyOtherComponent; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../node_modules/@angular/core/core.d.ts:7888:47 7888 (selector: Type<any> | Function | string, opts: { ~~~~~~~ 7889 read?: any; ~~~~~~~~~~~~~~~~~~~ 7890 static: boolean; ~~~~~~~~~~~~~~~~~~~~~~~~ 7891 }): any; ~~~~~ An argument for 'opts' was not provided.
Find this line in your code at the location specified in the error message:
@ViewChild(MyOtherComponent) myOtherComponent: MyOtherComponent;
and add
{static: false}
as second argument to the @ViewChild()
declaration:
@ViewChild(MyOtherComponent, {static: false}) myOtherComponent: MyOtherComponent;
In most cases, you want to use static: false
. See this post on StackOverflow for details on when to use static: true
as opposed to static: false
.
You want to run ng upgrade
to update your angular project libraries, but you see this error message:
The specified command ("upgrade") is invalid. For a list of available options, run "ng help". Did you mean "update"?
You need to run
ng update
instead of ng upgrade
(which is not a valid command).
This is what Did you mean "update"?
in the error message is intended to point you towards.
For a module of yours, you get an error message like this on load:
Error: Unexpected value 'undefined' declared by the module 'MyModule' at syntaxError (compiler.js:1021) at compiler.js:10623 at Array.forEach (<anonymous>) at CompileMetadataResolver.push../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (compiler.js:10621) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (compiler.js:23876) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (compiler.js:23857) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync (compiler.js:23817) at CompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:143) at core.js:4999 [...]
First, try to restart ng serve
. In some cases this will outright fix the issue.
The error message is caused by some element of your @NgModule
declarations: [ /* ... */ ]
to be undefined
(… declared by the module … in the error message should be taken literally, it’s in the declarations
!).
For example, if you have a @NgModule
declaration like this:
@NgModule({ imports: [ RecallCommonModule, CommonModule, MyRoutingModule ], declarations: [, MyDetailComponent, MySearchComponent ], providers: [] })
The issue is in the stray comma in the declarations
line: When compiled, it results in [undefined, MyDetailComponent, MySearchComponent]
. Removing the stray comma fixes the issue.
Another possible cause of this error is if one of the values in declarations is undefined.
For example if you have an import statement like
import { MyComponent } from './my.component';
in your module file, and, for some reason, MyComponent
is undefined
, this will cause the same error message to appear.
In order to track down which of your components in the declarations array, you could temporarily add a statement like this before your @NgModule
:
if(MyComponent === undefined) { console.log("MyComponent is undefined!"); }
In case you don’t have any of the issues above, follow the standard procedure:
Comment out every element in your declarations
array and see which causes the error message to disappear.
You are building an Angular6 application and in development mode everything works fine. However, if you build in production mode:
ng build --prod --aot
you see an error like this in the client:
main.4d1baabffbba5677af03.js:1 ERROR TypeError: i.ɵnov(...)._getAriaLabel is not a function at Object.updateRenderer (main.4d1baabffbba5677af03.js:1) at Object.updateRenderer (main.4d1baabffbba5677af03.js:1) [...]
The issue appears to be caused by incorrectly updated NodeJS modules. You can fix it by simply deleting your node_modules
folder:
rm -rf node_modules
Furthermore, it’s recommended to update @angular/cli
as the bug does not seem to be present in newer versions of @angular/cli
:
sudo npm i -g @angular/cli
If you encounter an error message like this:
Parser Error: Unexpected token 'px' at column 3 in [70px] in ng:///AppModule/MyComponent.html@5:34 ("="let string of strings">
look at the line the error is referring to. It will look similar to this:
<mat-expansion-panel-header [collapsedHeight]="70px">
You have two options of fixing this:
Option 1: Recommended if the value (70px
in this case) is always constant.
Remove the brackets from the attribute: [collapsedHeight]
to collapsedHeight
. The brackets mean that the value shall be interpreted as Javascript and removing them means interpreting the value as attribute. You code should look like this:
<mat-expansion-panel-header collapsedHeight="70px">
Option 2: Force angular to interpret the value (70px
in this case) as a string:
Add single quotes before and after the value makes it valid Javascript:
<mat-expansion-panel-header [collapsedHeight]="'70px'">
I recommend to use this option only if you expect the value to be a non-constant javascript expression in the future.
You encounter an error message like this:
ERROR TypeError: templateRef.createEmbeddedView is not a function at ViewContainerRef_.createEmbeddedView (core.js:11389) at NgIf._updateView (common.js:2843) at NgIf.set [as ngIfElse] (common.js:2815) at updateProp (core.js:12602) at checkAndUpdateDirectiveInline (core.js:12313) at checkAndUpdateNodeInline (core.js:13876) at checkAndUpdateNode (core.js:13819) at debugCheckAndUpdateNode (core.js:14712) at debugCheckDirectivesFn (core.js:14653) at Object.eval [as updateDirectives] (MyComponent.html:1)
in a component where you have a source code similar to this
<div *ngIf="myCondition ; else elseSection"> <!-- ... --> </div> <div #elseSection> <!-- ... --> </div>
Whatever element you reference in the *ngIf else clause can’t be any arbitrary component, but it must be a ng-template.
In order to solve this, change <div #elseSection>
to <ng-template #elseSection>
. Note that using just <template>
is deprecated since Angular4.
The resulting source code should look like this:
<div *ngIf="myCondition ; else elseSection"> <!-- ... --> </div> <ng-template #elseSection> <!-- ... --> </ng-template>
In your Angular2/4/5 application you see this error message:
Cannot find control with unspecified name attribute
Look for a statement in the HTML angular template like this:
[formControl]="myCtrl"
The error message means that myCtrl can’t be found. Check if this variable is present in your class – it needs be a FormControl
which you can import
from @angular/forms
:
import { FormControl } from '@angular/forms';
In my case, changing it to
[formControl]="myControl"
fixed the issue
In your Angular2/4/5 application you’re getting the following error message:
No provider for ControlContainer ("<div class="recall-container mat-elevation-z8">
You have not added the @angular/forms
FormsModule
to your module’s import
list.
Go to your app.module.ts and add this line to the imports:
import { FormsModule } from '@angular/forms';
and look for a line like this in your module definition:
imports: [ /* several import modules may be listed here */ ],
and add FormsModule
like this (if there are already imports, add FormsModule
to the list):
imports: [ FormsModule ],