Popular New Releases in Angular
bootstrap
4.6.1
angular
v14.0.0-next.14
TypeScript
TypeScript 4.7 Beta
storybook
ionic-framework
v6.1.3-nightly.20220422
Popular Libraries in Angular
by twbs javascript
156587 MIT
The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.
by angular typescript
80840 MIT
The modern web developer’s platform
by microsoft typescript
79882 Apache-2.0
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
by storybookjs typescript
70458 MIT
📓 The UI component explorer. Develop, document, & test React, Vue, Angular, Web Components, Ember, Svelte & more!
by angular javascript
59499 MIT
AngularJS - HTML enhanced for web apps!
by h5bp javascript
52642 MIT
A professional front-end template for building fast, robust, and adaptable web apps or sites.
by Semantic-Org javascript
49510 MIT
Semantic is a UI component framework based around useful principles from natural language.
by ionic-team typescript
46757 NOASSERTION
A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
by yangshun javascript
32705 MIT
⚡️ Front End interview preparation materials for busy engineers
Trending New libraries in Angular
by lgwebdream javascript
3960 NOASSERTION
🔥🔥🔥 前端面试,独有前端面试题详解,前端面试刷题必备,1000+前端面试真题,Html、Css、JavaScript、Vue、React、Node、TypeScript、Webpack、算法、网络与安全、浏览器
by rcbyr typescript
3299 MIT
The touch slider carousel with the most native feeling
by matteobruni typescript
3201 MIT
tsParticles - Easily create highly customizable particles, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.
by BuilderIO typescript
3098 MIT
The HTML-first framework. Initialize apps of any size with < 1kb JS
by Shpota go
2353 Apache-2.0
Generate a modern Web project with Go and Angular, React or Vue in seconds 🚀
by vime-js typescript
2103 MIT
Customizable, extensible, accessible and framework agnostic media player. Modern alternative to Video.js and Plyr. Supports HTML5, HLS, Dash, YouTube, Vimeo, Dailymotion...
by TinkoffCreditSystems typescript
1849 Apache-2.0
Angular UI Kit and components library for awesome people
by codesandbox typescript
1833 Apache-2.0
A component toolkit for creating live-running code editing experiences, using the power of CodeSandbox.
by trungk18 typescript
1724
A simplified Jira clone built with Angular, ng-zorro and Akita
Top Authors in Angular
1
107 Libraries
1910
2
98 Libraries
268439
3
94 Libraries
2560
4
69 Libraries
1131
5
60 Libraries
4078
6
57 Libraries
11878
7
53 Libraries
95801
8
51 Libraries
69625
9
48 Libraries
805
10
44 Libraries
22825
1
107 Libraries
1910
2
98 Libraries
268439
3
94 Libraries
2560
4
69 Libraries
1131
5
60 Libraries
4078
6
57 Libraries
11878
7
53 Libraries
95801
8
51 Libraries
69625
9
48 Libraries
805
10
44 Libraries
22825
Trending Kits in Angular
No Trending Kits are available at this moment for Angular
Trending Discussions on Angular
AngularFireModule and AngularFireDatabaseModule not being found in @angular/fire
After upgrading from Angular 12 to 13, cache is too large for Github
In Angular Material what does setting up global typography styles mean?
angular 13 ng build library fails (ivy partial compilation mode)
throwError(error) is now deprecated, but there is no new Error(HttpErrorResponse)
My project doesn't compile with optimization parameters after upgrading from angular 11 to angular 12
Data path "" must NOT have additional properties(extractCss) in Angular 13 while upgrading project
What's the .angular directory in the project root about?
Angular 6 to 12 Migration: Getting Multiple Warning: Css Minimizer Plugin: > Unexpected "$"
rxjs 7 update - Subject - Expected 1 arguments, but got 0
QUESTION
AngularFireModule and AngularFireDatabaseModule not being found in @angular/fire
Asked 2022-Apr-01 at 12:56I am trying to implement Firebase Realtime Database into a angular project and Im getting stuck at one of the very first steps. Importing AngularFireModule and AngularFireDatabaseModule. It gives me the following error:
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3
And here is how I am importing them:
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5
Am I missing something here? I have installed @angular/fire via the command
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5npm i firebase @angular/fire
6
and have also installed firebase tools. Here is a list of the Angular packages I currently have installed and their versions:
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5npm i firebase @angular/fire
6Angular CLI: 12.2.2
7Node: 14.17.4
8Package Manager: npm 6.14.14
9OS: win32 x64
10
11Angular: 12.2.3
12... animations, common, compiler, compiler-cli, core, forms
13... platform-browser, platform-browser-dynamic, router
14
15Package Version
16---------------------------------------------------------
17@angular-devkit/architect 0.1202.2
18@angular-devkit/build-angular 12.2.2
19@angular-devkit/core 12.2.2
20@angular-devkit/schematics 12.2.2
21@angular/cli 12.2.2
22@angular/fire 7.0.0
23@schematics/angular 12.2.2
24rxjs 6.6.7
25typescript 4.3.5
26
I do apologise if this is all excessive information but I am completely stuck as to what the issue is. Any help would be GREATLY appreciated. Right now my suspicion is that its a compatibility issue or perhaps a feature that doesnt exist anymore on the latest versions but I really dont know.
ANSWER
Answered 2021-Aug-26 at 13:20AngularFire 7.0.0 was launched yesterday with a new API that has a lot of bundle size reduction benefits.
Instead of top level classes like AngularFireDatabase
, you can now import smaller independent functions.
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5npm i firebase @angular/fire
6Angular CLI: 12.2.2
7Node: 14.17.4
8Package Manager: npm 6.14.14
9OS: win32 x64
10
11Angular: 12.2.3
12... animations, common, compiler, compiler-cli, core, forms
13... platform-browser, platform-browser-dynamic, router
14
15Package Version
16---------------------------------------------------------
17@angular-devkit/architect 0.1202.2
18@angular-devkit/build-angular 12.2.2
19@angular-devkit/core 12.2.2
20@angular-devkit/schematics 12.2.2
21@angular/cli 12.2.2
22@angular/fire 7.0.0
23@schematics/angular 12.2.2
24rxjs 6.6.7
25typescript 4.3.5
26import { list } from '@angular/fire/database';
27
The initialization process is a bit different too as it has a more flexible API for specifying configurations.
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5npm i firebase @angular/fire
6Angular CLI: 12.2.2
7Node: 14.17.4
8Package Manager: npm 6.14.14
9OS: win32 x64
10
11Angular: 12.2.3
12... animations, common, compiler, compiler-cli, core, forms
13... platform-browser, platform-browser-dynamic, router
14
15Package Version
16---------------------------------------------------------
17@angular-devkit/architect 0.1202.2
18@angular-devkit/build-angular 12.2.2
19@angular-devkit/core 12.2.2
20@angular-devkit/schematics 12.2.2
21@angular/cli 12.2.2
22@angular/fire 7.0.0
23@schematics/angular 12.2.2
24rxjs 6.6.7
25typescript 4.3.5
26import { list } from '@angular/fire/database';
27@NgModule({
28 imports: [
29 provideFirebaseApp(() => initializeApp(config)),
30 provideFirestore(() => {
31 const firestore = getFirestore();
32 connectEmulator(firestore, 'localhost', 8080);
33 enableIndexedDbPersistence(firestore);
34 return firestore;
35 }),
36 provideStorage(() => getStorage()),
37 ],
38})
39
If you want to proceed with the older API there's a compatibility layer.
1Module '"@angular/fire"' has no exported member 'AngularFireModule'.ts(2305)
2Module '"@angular/fire/database"' has no exported member 'AngularFireDatabaseModule'.
3import {AngularFireModule } from '@angular/fire';
4import {AngularFireDatabaseModule} from '@angular/fire/database'
5npm i firebase @angular/fire
6Angular CLI: 12.2.2
7Node: 14.17.4
8Package Manager: npm 6.14.14
9OS: win32 x64
10
11Angular: 12.2.3
12... animations, common, compiler, compiler-cli, core, forms
13... platform-browser, platform-browser-dynamic, router
14
15Package Version
16---------------------------------------------------------
17@angular-devkit/architect 0.1202.2
18@angular-devkit/build-angular 12.2.2
19@angular-devkit/core 12.2.2
20@angular-devkit/schematics 12.2.2
21@angular/cli 12.2.2
22@angular/fire 7.0.0
23@schematics/angular 12.2.2
24rxjs 6.6.7
25typescript 4.3.5
26import { list } from '@angular/fire/database';
27@NgModule({
28 imports: [
29 provideFirebaseApp(() => initializeApp(config)),
30 provideFirestore(() => {
31 const firestore = getFirestore();
32 connectEmulator(firestore, 'localhost', 8080);
33 enableIndexedDbPersistence(firestore);
34 return firestore;
35 }),
36 provideStorage(() => getStorage()),
37 ],
38})
39import { AngularFireModule} from '@angular/fire/compat'
40import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
41
QUESTION
After upgrading from Angular 12 to 13, cache is too large for Github
Asked 2022-Mar-28 at 18:10I recently upgraded all of my dependencies in package.json to the latest. I went from Angular 12.2.0 to 13.0.1 and github is now rejecting my push with the following file size error. Is there some setting I need to define in angular.json build profile that will help minimize these cache file sizes?
1remote: warning: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/3.pack is 54.01 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
2remote: warning: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/2.pack is 56.42 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
3remote: error: Trace: 0b9557fffbe30aac33f6d9858ef97559341c5c1614ace35524fcba85ac99ca76
4remote: error: See http://git.io/iEPt8g for more information.
5remote: error: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/3.pack is 122.06 MB; this exceeds GitHub's file size limit of 100.00 MB
6remote: error: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/5.pack is 123.92 MB; this exceeds GitHub's file size limit of 100.00 MB
7remote: error: File .angular/cache/angular-webpack/f48e9bc724ec0d5ae9a9d2fed858970d0a503f10/0.pack is 154.05 MB; this exceeds GitHub's file size limit of 100.00 MB
8remote: error: File .angular/cache/angular-webpack/9327900b3187f0b6351b4801d208e7b58f1af17e/0.pack is 165.50 MB; this exceeds GitHub's file size limit of 100.00 MB
9remote: error: File .angular/cache/angular-webpack/663bcd30d50863949acf1c25f02b95cab85c248a/0.pack is 151.56 MB; this exceeds GitHub's file size limit of 100.00 MB
10remote: error: File .angular/cache/angular-webpack/663bcd30d50863949acf1c25f02b95cab85c248a/0.pack is 151.55 MB; this exceeds GitHub's file size limit of 100.00 MB
11remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
12
Edit:
I created this repo with Angular cli and have been maintaining and updating through many versions of Angular and had no issue until this latest update.
The .gitignore file is in the root of the application and matches the suggested example:
When adding
/.angular/cache
to the gitignore file, I rungit rm -rf --cached . && git add . && git commit -m 'fix(gitignore): add angular cache' && git push --set-upstream origin chore/bump-deps
but still get the file size error.
ANSWER
Answered 2021-Nov-24 at 16:53Make sure your .gitignore
is in the parent folder of .angular
.
In that .gitignore
file, a simple .angular/cache/
should be enough to ignore that subfolder content.
Check it with:
1remote: warning: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/3.pack is 54.01 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
2remote: warning: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/2.pack is 56.42 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
3remote: error: Trace: 0b9557fffbe30aac33f6d9858ef97559341c5c1614ace35524fcba85ac99ca76
4remote: error: See http://git.io/iEPt8g for more information.
5remote: error: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/3.pack is 122.06 MB; this exceeds GitHub's file size limit of 100.00 MB
6remote: error: File .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/5.pack is 123.92 MB; this exceeds GitHub's file size limit of 100.00 MB
7remote: error: File .angular/cache/angular-webpack/f48e9bc724ec0d5ae9a9d2fed858970d0a503f10/0.pack is 154.05 MB; this exceeds GitHub's file size limit of 100.00 MB
8remote: error: File .angular/cache/angular-webpack/9327900b3187f0b6351b4801d208e7b58f1af17e/0.pack is 165.50 MB; this exceeds GitHub's file size limit of 100.00 MB
9remote: error: File .angular/cache/angular-webpack/663bcd30d50863949acf1c25f02b95cab85c248a/0.pack is 151.56 MB; this exceeds GitHub's file size limit of 100.00 MB
10remote: error: File .angular/cache/angular-webpack/663bcd30d50863949acf1c25f02b95cab85c248a/0.pack is 151.55 MB; this exceeds GitHub's file size limit of 100.00 MB
11remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
12git check-ignore -v -- .angular/cache/angular-webpack/72163742903fc8ba00e684045de261c2e3a2fb86/2.pack
13
You can see an example in ganatan/angular-starter/.gitignore
(from an Angular 13 Example Starter project), where /.angular/cache/
is used, to anchor the rule to the top folder of the repository.
The OP S. Taylor confirms in the comments:
I'm pretty sure that was my issue.
I abandoned thedev
branch and updated my dependencies without using the compound commands likegit add . && git commit -m 'fix(gitignore): add angular cache'
.
Making sure to note what was staged.
QUESTION
In Angular Material what does setting up global typography styles mean?
Asked 2022-Mar-16 at 01:12When using ng add @angular/material
to add Material support to an Angular project there is a prompt Set up global Angular Material typography styles?
What does this even mean? The documentation states the prompt appears, but does not describe what it actually means.
ANSWER
Answered 2022-Mar-16 at 01:12By default, Angular Material doesn’t apply global CSS. Meaning that a standard element (eg. <h1>
) will not have Angular materials' styles applied to it.
So, when configured this way, in order to apply Angular material styles to a broad section of your HTML, you can use the mat-typography
class
1<h1>This header doesn't have Angular Material styling</h1>
2<section class="mat-typography">
3<h1>This header does have Angular Material styling</h1>
4</section>
5
If you set up global typography styles; then the first <h1>
will already be styled.
QUESTION
angular 13 ng build library fails (ivy partial compilation mode)
Asked 2022-Mar-04 at 12:53Recently I was having a problem installing an npm package (that used node-gyp). I tried upgrading the minor version of node from version 16.13.0 to 16.13.1 and upgrading my angular cli from 13.0.2 to 13.2.0. Once I got the package to install I generated a library with ng g library new-library
. I don't know what what actually broke it, but now whenever I try to build alibrary it produces an error. I try ng build my-lib
and get the below error.
1✖ Compiling with Angular sources in Ivy partial compilation mode.
2Transform failed with 1 error:
3error: Invalid version: "15.2-15.3"
4
I tried reverting the version of node and angular cli but it didn't fix the problem. I even reverted the code to its original state and I get the error now. Is this a problem with my environment? How do I fix this issue?
ANSWER
Answered 2022-Jan-30 at 07:21This is a bug in Angular CLI 13.2.0
.
Temporary solution:
Removing content configurating .browserslistrc
file from root project.
more info
QUESTION
throwError(error) is now deprecated, but there is no new Error(HttpErrorResponse)
Asked 2022-Mar-01 at 00:42Apparently throwError(error)
is now deprecated. The IntelliSense of VS Code suggests throwError(() => new Error('error')
. new Error(...)
accepts only strings. What's the correct way to replace it without breaking my HttpErrorHandlerService
?
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150import { Injectable } from '@angular/core';
151import {
152 HttpRequest,
153 HttpHandler,
154 HttpEvent,
155 HttpInterceptor,
156 HttpErrorResponse
157} from '@angular/common/http';
158import {
159 BehaviorSubject,
160 catchError,
161 EMPTY,
162 filter,
163 finalize,
164 Observable,
165 switchMap,
166 take,
167 throwError
168} from 'rxjs';
169
170import { AuthService } from '@core/services';
171import { AuthResponse } from '@core/types';
172
173@Injectable()
174export class AuthInterceptor implements HttpInterceptor {
175 private refreshTokenInProgress: boolean;
176 private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
177
178 constructor(private authService: AuthService) {}
179
180 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
181 return next
182 .handle(this.performRequest(request))
183 .pipe(
184 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
185 );
186 }
187
188 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
189 const accessToken = this.authService.getAccessToken();
190
191 let headers = request.headers;
192 if (accessToken) {
193 headers = headers.set('Authorization', `Bearer ${accessToken}`);
194 }
195
196 return request.clone({ headers });
197 }
198
199 private processRequestError(
200 error: HttpErrorResponse,
201 request: HttpRequest<any>,
202 next: HttpHandler
203 ): Observable<HttpEvent<any>> {
204 console.log('auth interceptor called');
205
206 if (
207 error instanceof HttpErrorResponse &&
208 error.status === 401 &&
209 this.authService.isSignedIn()
210 ) {
211 return this.refreshToken(request, next);
212 }
213
214 return throwError(error);
215 }
216
217 private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
218 console.log('refresh token in auth.interceptor called');
219
220 // in case the page consists of more than one requests
221 if (!this.refreshTokenInProgress) {
222 this.refreshToken$.next(null);
223 this.refreshTokenInProgress = true;
224
225 return this.authService.refreshToken().pipe(
226 switchMap((response) => {
227 if (response) {
228 this.refreshToken$.next(response);
229 return next.handle(this.performRequest(request));
230 }
231
232 this.authService.signOut();
233 return throwError(() => new Error("RefreshTokenFailed"));
234 }),
235 catchError((error) => {
236 this.authService.signOut();
237 return throwError(error);
238 }),
239 finalize(() => (this.refreshTokenInProgress = false))
240 );
241 } else {
242 // wait while getting new token
243 return this.refreshToken$.pipe(
244 filter((result) => result !== null),
245 take(1),
246 switchMap(() => next.handle(this.performRequest(request)))
247 );
248 }
249 }
250}
251
252
ANSWER
Answered 2021-Aug-04 at 19:08Instead of this:
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150import { Injectable } from '@angular/core';
151import {
152 HttpRequest,
153 HttpHandler,
154 HttpEvent,
155 HttpInterceptor,
156 HttpErrorResponse
157} from '@angular/common/http';
158import {
159 BehaviorSubject,
160 catchError,
161 EMPTY,
162 filter,
163 finalize,
164 Observable,
165 switchMap,
166 take,
167 throwError
168} from 'rxjs';
169
170import { AuthService } from '@core/services';
171import { AuthResponse } from '@core/types';
172
173@Injectable()
174export class AuthInterceptor implements HttpInterceptor {
175 private refreshTokenInProgress: boolean;
176 private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
177
178 constructor(private authService: AuthService) {}
179
180 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
181 return next
182 .handle(this.performRequest(request))
183 .pipe(
184 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
185 );
186 }
187
188 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
189 const accessToken = this.authService.getAccessToken();
190
191 let headers = request.headers;
192 if (accessToken) {
193 headers = headers.set('Authorization', `Bearer ${accessToken}`);
194 }
195
196 return request.clone({ headers });
197 }
198
199 private processRequestError(
200 error: HttpErrorResponse,
201 request: HttpRequest<any>,
202 next: HttpHandler
203 ): Observable<HttpEvent<any>> {
204 console.log('auth interceptor called');
205
206 if (
207 error instanceof HttpErrorResponse &&
208 error.status === 401 &&
209 this.authService.isSignedIn()
210 ) {
211 return this.refreshToken(request, next);
212 }
213
214 return throwError(error);
215 }
216
217 private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
218 console.log('refresh token in auth.interceptor called');
219
220 // in case the page consists of more than one requests
221 if (!this.refreshTokenInProgress) {
222 this.refreshToken$.next(null);
223 this.refreshTokenInProgress = true;
224
225 return this.authService.refreshToken().pipe(
226 switchMap((response) => {
227 if (response) {
228 this.refreshToken$.next(response);
229 return next.handle(this.performRequest(request));
230 }
231
232 this.authService.signOut();
233 return throwError(() => new Error("RefreshTokenFailed"));
234 }),
235 catchError((error) => {
236 this.authService.signOut();
237 return throwError(error);
238 }),
239 finalize(() => (this.refreshTokenInProgress = false))
240 );
241 } else {
242 // wait while getting new token
243 return this.refreshToken$.pipe(
244 filter((result) => result !== null),
245 take(1),
246 switchMap(() => next.handle(this.performRequest(request)))
247 );
248 }
249 }
250}
251
252 catchError((error) => {
253 this.authService.signOut();
254 return throwError(error);
255 }),
256
You could try this:
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150import { Injectable } from '@angular/core';
151import {
152 HttpRequest,
153 HttpHandler,
154 HttpEvent,
155 HttpInterceptor,
156 HttpErrorResponse
157} from '@angular/common/http';
158import {
159 BehaviorSubject,
160 catchError,
161 EMPTY,
162 filter,
163 finalize,
164 Observable,
165 switchMap,
166 take,
167 throwError
168} from 'rxjs';
169
170import { AuthService } from '@core/services';
171import { AuthResponse } from '@core/types';
172
173@Injectable()
174export class AuthInterceptor implements HttpInterceptor {
175 private refreshTokenInProgress: boolean;
176 private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
177
178 constructor(private authService: AuthService) {}
179
180 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
181 return next
182 .handle(this.performRequest(request))
183 .pipe(
184 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
185 );
186 }
187
188 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
189 const accessToken = this.authService.getAccessToken();
190
191 let headers = request.headers;
192 if (accessToken) {
193 headers = headers.set('Authorization', `Bearer ${accessToken}`);
194 }
195
196 return request.clone({ headers });
197 }
198
199 private processRequestError(
200 error: HttpErrorResponse,
201 request: HttpRequest<any>,
202 next: HttpHandler
203 ): Observable<HttpEvent<any>> {
204 console.log('auth interceptor called');
205
206 if (
207 error instanceof HttpErrorResponse &&
208 error.status === 401 &&
209 this.authService.isSignedIn()
210 ) {
211 return this.refreshToken(request, next);
212 }
213
214 return throwError(error);
215 }
216
217 private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
218 console.log('refresh token in auth.interceptor called');
219
220 // in case the page consists of more than one requests
221 if (!this.refreshTokenInProgress) {
222 this.refreshToken$.next(null);
223 this.refreshTokenInProgress = true;
224
225 return this.authService.refreshToken().pipe(
226 switchMap((response) => {
227 if (response) {
228 this.refreshToken$.next(response);
229 return next.handle(this.performRequest(request));
230 }
231
232 this.authService.signOut();
233 return throwError(() => new Error("RefreshTokenFailed"));
234 }),
235 catchError((error) => {
236 this.authService.signOut();
237 return throwError(error);
238 }),
239 finalize(() => (this.refreshTokenInProgress = false))
240 );
241 } else {
242 // wait while getting new token
243 return this.refreshToken$.pipe(
244 filter((result) => result !== null),
245 take(1),
246 switchMap(() => next.handle(this.performRequest(request)))
247 );
248 }
249 }
250}
251
252 catchError((error) => {
253 this.authService.signOut();
254 return throwError(error);
255 }),
256 catchError((error) => {
257 this.authService.signOut();
258 return throwError(() => error);
259 }),
260
I wasn't able to test it thoroughly, but a simple attempt seemed to work.
This was my simple test (using RxJS v7.2):
Service
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150import { Injectable } from '@angular/core';
151import {
152 HttpRequest,
153 HttpHandler,
154 HttpEvent,
155 HttpInterceptor,
156 HttpErrorResponse
157} from '@angular/common/http';
158import {
159 BehaviorSubject,
160 catchError,
161 EMPTY,
162 filter,
163 finalize,
164 Observable,
165 switchMap,
166 take,
167 throwError
168} from 'rxjs';
169
170import { AuthService } from '@core/services';
171import { AuthResponse } from '@core/types';
172
173@Injectable()
174export class AuthInterceptor implements HttpInterceptor {
175 private refreshTokenInProgress: boolean;
176 private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
177
178 constructor(private authService: AuthService) {}
179
180 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
181 return next
182 .handle(this.performRequest(request))
183 .pipe(
184 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
185 );
186 }
187
188 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
189 const accessToken = this.authService.getAccessToken();
190
191 let headers = request.headers;
192 if (accessToken) {
193 headers = headers.set('Authorization', `Bearer ${accessToken}`);
194 }
195
196 return request.clone({ headers });
197 }
198
199 private processRequestError(
200 error: HttpErrorResponse,
201 request: HttpRequest<any>,
202 next: HttpHandler
203 ): Observable<HttpEvent<any>> {
204 console.log('auth interceptor called');
205
206 if (
207 error instanceof HttpErrorResponse &&
208 error.status === 401 &&
209 this.authService.isSignedIn()
210 ) {
211 return this.refreshToken(request, next);
212 }
213
214 return throwError(error);
215 }
216
217 private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
218 console.log('refresh token in auth.interceptor called');
219
220 // in case the page consists of more than one requests
221 if (!this.refreshTokenInProgress) {
222 this.refreshToken$.next(null);
223 this.refreshTokenInProgress = true;
224
225 return this.authService.refreshToken().pipe(
226 switchMap((response) => {
227 if (response) {
228 this.refreshToken$.next(response);
229 return next.handle(this.performRequest(request));
230 }
231
232 this.authService.signOut();
233 return throwError(() => new Error("RefreshTokenFailed"));
234 }),
235 catchError((error) => {
236 this.authService.signOut();
237 return throwError(error);
238 }),
239 finalize(() => (this.refreshTokenInProgress = false))
240 );
241 } else {
242 // wait while getting new token
243 return this.refreshToken$.pipe(
244 filter((result) => result !== null),
245 take(1),
246 switchMap(() => next.handle(this.performRequest(request)))
247 );
248 }
249 }
250}
251
252 catchError((error) => {
253 this.authService.signOut();
254 return throwError(error);
255 }),
256 catchError((error) => {
257 this.authService.signOut();
258 return throwError(() => error);
259 }),
260 getProducts(): Observable<IProduct[]> {
261 return this.http.get<IProduct[]>(this.productUrl)
262 .pipe(
263 tap(data => console.log('All: ', JSON.stringify(data))),
264 catchError(this.handleError)
265 );
266 }
267
268 private handleError(err: HttpErrorResponse): Observable<never> {
269 // just a test ... more could would go here
270 return throwError(() => err);
271 }
272
Notice that err
here is of type HttpErrorResponse
.
Component
1import { Injectable } from '@angular/core';
2import {
3 HttpEvent,
4 HttpInterceptor,
5 HttpHandler,
6 HttpRequest,
7 HttpErrorResponse,
8 HttpResponse,
9 HttpHeaders
10} from '@angular/common/http';
11import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
12
13import { HttpErrorHandlerService } from '@core/services';
14
15@Injectable()
16export class HttpErrorInterceptor implements HttpInterceptor {
17 private readonly APP_XHR_TIMEOUT = 6000;
18
19 constructor(private errorHandlerService: HttpErrorHandlerService) {}
20
21 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 return next.handle(this.performRequest(request)).pipe(
23 timeout(this.APP_XHR_TIMEOUT),
24 map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
25 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
26 finalize(this.handleRequestCompleted.bind(this))
27 );
28 }
29
30 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
31 let headers: HttpHeaders = request.headers;
32 //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
33 return request.clone({ headers });
34 }
35
36 private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
37 if (event instanceof HttpResponse) {
38 event = event.clone({ body: event.body.response });
39 }
40 return event;
41 }
42
43 private processRequestError(
44 error: HttpErrorResponse,
45 request: HttpRequest<any>,
46 next: HttpHandler
47 ): Observable<HttpEvent<any>> {
48 console.log('http error response');
49
50 if ([401].includes(error.status)) {
51 return throwError(error);
52 }
53
54 this.errorHandlerService.handle(error);
55
56 return throwError(error);
57 }
58
59 private handleRequestCompleted(): void {
60 // console.log(`Request finished`);
61 }
62}
63
64import { Injectable } from '@angular/core';
65import { HttpErrorResponse } from '@angular/common/http';
66
67import { MessageService } from 'primeng/api';
68import { TimeoutError } from 'rxjs';
69
70/**
71 * Shows a user-friendly error message when a HTTP request fails.
72 */
73@Injectable({
74 providedIn: 'root'
75})
76export class HttpErrorHandlerService {
77 constructor(private messageService: MessageService) {}
78
79 handle(error: Error | HttpErrorResponse) {
80 if (error instanceof TimeoutError) {
81 return this.openDialog('error', `Няма връзка до сървъра.`);
82 }
83
84 if (error instanceof HttpErrorResponse && error.error && error.error.message) {
85 return this.openDialog('error', error.error.message);
86 }
87
88 if (error instanceof Error) {
89 switch (error.message) {
90 default:
91 return this.openDialog('error', `An unknown error occurred`);
92 }
93 }
94
95 // Generic HTTP errors
96 switch (error.status) {
97 case 400:
98 switch (error.error) {
99 case 'invalid_username_or_password':
100 return this.openDialog('error', 'Невалидно потребителско име или парола');
101 default:
102 return this.openDialog('error', 'Bad request');
103 }
104
105 case 401:
106 return this.openDialog('error', 'Ще трябва да се логнете отново');
107
108 case 403:
109 return this.openDialog('error', `You don't have the required permissions`);
110
111 case 404:
112 return this.openDialog('error', 'Resource not found');
113
114 case 422:
115 return this.openDialog('error', 'Invalid data provided');
116
117 case 500:
118 case 501:
119 case 502:
120 case 503:
121 return this.openDialog('error', 'An internal server error occurred');
122
123 case -1:
124 return this.openDialog(
125 'error',
126 'You appear to be offline. Please check your internet connection and try again.'
127 );
128
129 case 0:
130 return this.openDialog('error', `CORS issue?`);
131
132 default:
133 return this.openDialog('error', `An unknown error occurred`);
134 }
135 }
136
137 private openDialog(severity: string, message: string) {
138 if (message?.trim()) {
139 this.messageService.add({
140 key: 'interceptor',
141 severity: severity,
142 summary: 'Информация',
143 detail: message,
144 life: 3000
145 });
146 }
147 }
148}
149
150import { Injectable } from '@angular/core';
151import {
152 HttpRequest,
153 HttpHandler,
154 HttpEvent,
155 HttpInterceptor,
156 HttpErrorResponse
157} from '@angular/common/http';
158import {
159 BehaviorSubject,
160 catchError,
161 EMPTY,
162 filter,
163 finalize,
164 Observable,
165 switchMap,
166 take,
167 throwError
168} from 'rxjs';
169
170import { AuthService } from '@core/services';
171import { AuthResponse } from '@core/types';
172
173@Injectable()
174export class AuthInterceptor implements HttpInterceptor {
175 private refreshTokenInProgress: boolean;
176 private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
177
178 constructor(private authService: AuthService) {}
179
180 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
181 return next
182 .handle(this.performRequest(request))
183 .pipe(
184 catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
185 );
186 }
187
188 private performRequest(request: HttpRequest<any>): HttpRequest<any> {
189 const accessToken = this.authService.getAccessToken();
190
191 let headers = request.headers;
192 if (accessToken) {
193 headers = headers.set('Authorization', `Bearer ${accessToken}`);
194 }
195
196 return request.clone({ headers });
197 }
198
199 private processRequestError(
200 error: HttpErrorResponse,
201 request: HttpRequest<any>,
202 next: HttpHandler
203 ): Observable<HttpEvent<any>> {
204 console.log('auth interceptor called');
205
206 if (
207 error instanceof HttpErrorResponse &&
208 error.status === 401 &&
209 this.authService.isSignedIn()
210 ) {
211 return this.refreshToken(request, next);
212 }
213
214 return throwError(error);
215 }
216
217 private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
218 console.log('refresh token in auth.interceptor called');
219
220 // in case the page consists of more than one requests
221 if (!this.refreshTokenInProgress) {
222 this.refreshToken$.next(null);
223 this.refreshTokenInProgress = true;
224
225 return this.authService.refreshToken().pipe(
226 switchMap((response) => {
227 if (response) {
228 this.refreshToken$.next(response);
229 return next.handle(this.performRequest(request));
230 }
231
232 this.authService.signOut();
233 return throwError(() => new Error("RefreshTokenFailed"));
234 }),
235 catchError((error) => {
236 this.authService.signOut();
237 return throwError(error);
238 }),
239 finalize(() => (this.refreshTokenInProgress = false))
240 );
241 } else {
242 // wait while getting new token
243 return this.refreshToken$.pipe(
244 filter((result) => result !== null),
245 take(1),
246 switchMap(() => next.handle(this.performRequest(request)))
247 );
248 }
249 }
250}
251
252 catchError((error) => {
253 this.authService.signOut();
254 return throwError(error);
255 }),
256 catchError((error) => {
257 this.authService.signOut();
258 return throwError(() => error);
259 }),
260 getProducts(): Observable<IProduct[]> {
261 return this.http.get<IProduct[]>(this.productUrl)
262 .pipe(
263 tap(data => console.log('All: ', JSON.stringify(data))),
264 catchError(this.handleError)
265 );
266 }
267
268 private handleError(err: HttpErrorResponse): Observable<never> {
269 // just a test ... more could would go here
270 return throwError(() => err);
271 }
272 ngOnInit(): void {
273 this.sub = this.productService.getProducts().subscribe({
274 next: products => {
275 this.products = products;
276 this.filteredProducts = this.products;
277 },
278 error: err => this.errorMessage = err.message
279 });
280 }
281
Here I was able to retrieve the message
property from the error response and display it in my UI.
Let me know if this works for you.
QUESTION
My project doesn't compile with optimization parameters after upgrading from angular 11 to angular 12
Asked 2022-Jan-31 at 19:50I just upgraded an environment with nrwl from angular version 11 to 12 with two angular applications and several libraries. After update when I try to compile using optimization settings:
angular.json
1{
2 ....
3 "optimization": {
4 "scripts": true,
5 "styles": {
6 "minify": true,
7 "inlineCritical": false
8 },
9 "fonts": true
10 },
11}
12
It gives me the following error (sass and scss component files):
1{
2 ....
3 "optimization": {
4 "scripts": true,
5 "styles": {
6 "minify": true,
7 "inlineCritical": false
8 },
9 "fonts": true
10 },
11}
12/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass - Error: /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass from Css Minimizer
13Error: Transform failed with 1 error:
14error: Invalid version: "15.2-15.3"
15 at failureErrorWithLog (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1493:15)
16 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1282:29
17 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:629:9
18 at handleIncomingPacket (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:726:9)
19 at Socket.readFromStdout (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:596:7)
20 at Socket.emit (events.js:315:20)
21 at addChunk (_stream_readable.js:309:12)
22 at readableAddChunk (_stream_readable.js:284:9)
23 at Socket.Readable.push (_stream_readable.js:223:10)
24 at Pipe.onStreamRead (internal/stream_base_commons.js:188:23)
25
Disabling styles.minify and fonts compiles without problems:
1{
2 ....
3 "optimization": {
4 "scripts": true,
5 "styles": {
6 "minify": true,
7 "inlineCritical": false
8 },
9 "fonts": true
10 },
11}
12/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass - Error: /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass from Css Minimizer
13Error: Transform failed with 1 error:
14error: Invalid version: "15.2-15.3"
15 at failureErrorWithLog (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1493:15)
16 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1282:29
17 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:629:9
18 at handleIncomingPacket (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:726:9)
19 at Socket.readFromStdout (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:596:7)
20 at Socket.emit (events.js:315:20)
21 at addChunk (_stream_readable.js:309:12)
22 at readableAddChunk (_stream_readable.js:284:9)
23 at Socket.Readable.push (_stream_readable.js:223:10)
24 at Pipe.onStreamRead (internal/stream_base_commons.js:188:23)
25"optimization": {
26 "scripts": true,
27 "styles": {
28 "minify": false,
29 "inlineCritical": false
30 },
31 "fonts": false
32 },
33}
34
ANSWER
Answered 2022-Jan-31 at 19:50Reason of the issue
It is expected browserslist to return an entry for each version ("safari 15.2", "safari 15.3") instead of a range ("safari 15.2-15.3"). So, this is just a bug in the parsing logic of Safari browser versions which needs to be corrected and will be done soon in fixed versions of Angular 12/Angular 13. Link to details is here.
IMPORTANT UPDATE:
This is fixed in v12.2.16 and v13.2.1, please update if you are experiencing this issue. Users on v11 shouldn't be affected. Link to details is here. If you can not/do not want to update for any reason, then one of the workarounds below can be used.
Workarounds:
Modify .browserslistrc
Add to .browserslistrc such lines:
1{
2 ....
3 "optimization": {
4 "scripts": true,
5 "styles": {
6 "minify": true,
7 "inlineCritical": false
8 },
9 "fonts": true
10 },
11}
12/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass - Error: /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass from Css Minimizer
13Error: Transform failed with 1 error:
14error: Invalid version: "15.2-15.3"
15 at failureErrorWithLog (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1493:15)
16 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1282:29
17 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:629:9
18 at handleIncomingPacket (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:726:9)
19 at Socket.readFromStdout (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:596:7)
20 at Socket.emit (events.js:315:20)
21 at addChunk (_stream_readable.js:309:12)
22 at readableAddChunk (_stream_readable.js:284:9)
23 at Socket.Readable.push (_stream_readable.js:223:10)
24 at Pipe.onStreamRead (internal/stream_base_commons.js:188:23)
25"optimization": {
26 "scripts": true,
27 "styles": {
28 "minify": false,
29 "inlineCritical": false
30 },
31 "fonts": false
32 },
33}
34not ios_saf 15.2-15.3 # temporary solution to avoid build issues https://github.com/nrwl/nx/issues/8768
35not safari 15.2-15.3 # temporary solution to avoid build issues https://github.com/nrwl/nx/issues/8768
36
It has to come AFTER any mentions of ios_saf or safari. Otherwise, it doesn't work. Link to workaround is here.
Erase content of .browserslistrc
Erasing content of .browserslistrc helps to fix builds. Link to workaround is here.
Delete .browserslistrc
Deletion of .browserslistrc helps to fix builds. Link to workaround is here.
Install caniuse-lite
Add caniuse-lite package:
1{
2 ....
3 "optimization": {
4 "scripts": true,
5 "styles": {
6 "minify": true,
7 "inlineCritical": false
8 },
9 "fonts": true
10 },
11}
12/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass - Error: /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/libs/ui-share-components/src/lib/top-panel/top-panel/top-panel.component.sass from Css Minimizer
13Error: Transform failed with 1 error:
14error: Invalid version: "15.2-15.3"
15 at failureErrorWithLog (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1493:15)
16 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:1282:29
17 at /home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:629:9
18 at handleIncomingPacket (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:726:9)
19 at Socket.readFromStdout (/home/jose/WORK/Rental/REAL/APPS/angular-nx-ws/node_modules/@angular-devkit/build-angular/node_modules/esbuild/lib/main.js:596:7)
20 at Socket.emit (events.js:315:20)
21 at addChunk (_stream_readable.js:309:12)
22 at readableAddChunk (_stream_readable.js:284:9)
23 at Socket.Readable.push (_stream_readable.js:223:10)
24 at Pipe.onStreamRead (internal/stream_base_commons.js:188:23)
25"optimization": {
26 "scripts": true,
27 "styles": {
28 "minify": false,
29 "inlineCritical": false
30 },
31 "fonts": false
32 },
33}
34not ios_saf 15.2-15.3 # temporary solution to avoid build issues https://github.com/nrwl/nx/issues/8768
35not safari 15.2-15.3 # temporary solution to avoid build issues https://github.com/nrwl/nx/issues/8768
36npm install caniuse-lite@1.0.30001303 --save-dev --save-exact
37
Link to workaround is here.
QUESTION
Data path "" must NOT have additional properties(extractCss) in Angular 13 while upgrading project
Asked 2022-Jan-27 at 14:41I am facing an issue while upgrading my project from angular 8.2.1 to angular 13 version.
After a successful upgrade while preparing a build it is giving me the following error.
1Data path "" must NOT have additional properties(extractCss).
2
I already renamed styleext
with style
in the angular.json file, but still not able to find the root cause for this error.
angular.json file is as follows.
1Data path "" must NOT have additional properties(extractCss).
2 {
3 "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
4 "version": 1,
5 "newProjectRoot": "projects",
6 "projects": {
7 "qiwkCollaborator": {
8 "projectType": "application",
9 "schematics": {
10 "@schematics/angular:component": {
11 "style": "scss"
12 }
13 },
14 "root": "",
15 "sourceRoot": "src",
16 "prefix": "app",
17 "architect": {
18 "build": {
19
20 /* "configurations": {
21 "fr": {
22 "aot": true,
23 "outputPath": "dist/qwikCollaborator/fr/",
24 "i18nFile": "src/translate/messages.fr.xlf",
25 "i18nFormat": "xlf",
26 "i18nLocale": "fr",
27 "i18nMissingTranslation": "error"
28 },
29 "en": {
30 "aot": true,
31 "outputPath": "dist/qwikCollaborator/en/",
32 "i18nFile": "src/translate/messages.en.xlf",
33 "i18nFormat": "xlf",
34 "i18nLocale": "en",
35 "i18nMissingTranslation": "error"
36 }
37 },*/
38 "builder": "@angular-devkit/build-angular:browser",
39 "options": {
40 "outputPath": "dist/qiwkCollaborator",
41 "index": "src/index.html",
42 "main": "src/main.ts",
43 "polyfills": "src/polyfills.ts",
44 "tsConfig": "tsconfig.app.json",
45 "aot": false,
46 "assets": [
47 "src/favicon.ico",
48 "src/assets"
49 ],
50 "styles": [
51 "src/styles.scss",
52 "src/assets/css/custom-mobile.css",
53 "src/assets/css/custom.css"
54 ],
55 "scripts": [
56 "node_modules/jquery/dist/jquery.min.js",
57 "src/assets/js/qwikCollaborator.js"
58 ]
59 },
60 "configurations": {
61 "es5": {
62 "tsConfig": "./tsconfig.es5.json"
63 },
64 "production": {
65 "fileReplacements": [
66 {
67 "replace": "src/environments/environment.ts",
68 "with": "src/environments/environment.prod.ts"
69 }
70 ],
71 "optimization": true,
72 "outputHashing": "all",
73 "sourceMap": false,
74 "extractCss": true,
75 "namedChunks": false,
76 "aot": true,
77 "extractLicenses": true,
78 "vendorChunk": false,
79 "buildOptimizer": true,
80 "budgets": [
81 {
82 "type": "initial",
83 "maximumWarning": "2mb",
84 "maximumError": "5mb"
85 },
86 {
87 "type": "anyComponentStyle",
88 "maximumWarning": "6kb",
89 "maximumError": "10kb"
90 }
91 ]
92 }
93 }
94 },
95 "serve": {
96 /* "configurations": {
97 "fr": {
98 "browserTarget": "qwikCollaborator:build:fr"
99 },
100 "en": {
101 "browserTarget": "qwikCollaborator:build:en"
102 } ,
103 },*/
104 "builder": "@angular-devkit/build-angular:dev-server",
105 "options": {
106 "browserTarget": "qiwkCollaborator:build"
107 },
108
109 "configurations": {
110 "es5": {
111 "browserTarget": "qiwkCollaborator:build:es5"
112 },
113 "production": {
114 "browserTarget": "qiwkCollaborator:build:es5"
115 }
116 }
117 },
118 "extract-i18n": {
119 "builder": "@angular-devkit/build-angular:extract-i18n",
120 "options": {
121 "browserTarget": "qiwkCollaborator:build"
122 }
123 },
124 "test": {
125 "builder": "@angular-devkit/build-angular:karma",
126 "options": {
127 "main": "src/test.ts",
128 "polyfills": "src/polyfills.ts",
129 "tsConfig": "tsconfig.spec.json",
130 "karmaConfig": "karma.conf.js",
131 "assets": [
132 "src/favicon.ico",
133 "src/assets"
134 ],
135 "styles": [
136 "src/styles.scss"
137 ],
138 "scripts": ["../node_modules/jspdf/dist/jspdf.min.js"]
139 }
140 },
141 "lint": {
142 "builder": "@angular-devkit/build-angular:tslint",
143 "options": {
144 "tsConfig": [
145 "tsconfig.app.json",
146 "tsconfig.spec.json",
147 "e2e/tsconfig.json"
148 ],
149 "exclude": [
150 "**/node_modules/**"
151 ]
152 }
153 },
154 "e2e": {
155 "builder": "@angular-devkit/build-angular:protractor",
156 "options": {
157 "protractorConfig": "e2e/protractor.conf.js",
158 "devServerTarget": "qiwkCollaborator:serve"
159 },
160 "configurations": {
161 "production": {
162 "devServerTarget": "qiwkCollaborator:serve:production"
163 }
164 }
165 }
166 }
167 }},
168 "defaultProject": "qiwkCollaborator"
169}
170
How to get rid of this additional property?
can anyone help me with this?
thanks in advance!
ANSWER
Answered 2021-Dec-14 at 12:45Just remove the "extractCss": true
from your production environment, it will resolve the problem.
The reason about it is extractCss is deprecated, and it's value is true by default. See more here: Extracting CSS into JS with Angular 11 (deprecated extractCss)
QUESTION
What's the .angular directory in the project root about?
Asked 2021-Dec-02 at 10:07According to the docs, there's nothing called .angular being regarded. Yet, in my project, I get that directory, immediately in the root of the project (on the same level as e.g. package.json).
It wasn't there before because my .gitignore would've barked at it. Currently, I'm trying out the latest Angular version, 13.0 and I conclude that it's a new addition to the tooling. Probably, it's some temporary stuff, since its contents are the following.
- .angular/cache/angular-webpack
- .angular/cache/babel-webpack
It was pointless to google .angular directory dot what is and the only (semi-)relevant hit I got was the docs linked above.
What's up with .angular directory and do I need to care (and/or version control it)?
ANSWER
Answered 2021-Dec-02 at 10:07".angular/cache" folder should be ignored by your version control system (git, svn etc...)
Example for git, add this line to .gitignore file
1.angular/cache
2
(source : ng new command with @angular/cli v13)
QUESTION
Angular 6 to 12 Migration: Getting Multiple Warning: Css Minimizer Plugin: > Unexpected "$"
Asked 2021-Nov-19 at 17:27After migrating my angular 6 project to 12. I am getting multiple warning in terminal
if in angular.json i set optimisation: false configuration then all issue get resolved but i don't want to make this changes it should be true only.
with optimisation: true i am getting all these warnings:-
Earlier same code was working fine without any warning.
1assets/.../variables.scss - Warning: Css Minimizer Plugin: > assets/.../variables.scss:6:0: warning: Unexpected "$"
2 6 │ $color-normal-gray:#8a8a8a;
3 ╵ ^
4
5assets/.../global.scss - Warning: Css Minimizer Plugin: >
6assets/.../global.scss:285:2: warning: Expected identifier but found "."
7 285 │ .dropdown-menu{
8 ╵ ^
9
10assets/.../global.scss - Warning: Css Minimizer Plugin: >
11assets/.../global.scss:255:6: warning: Expected identifier but found "*"
12 255 │ *background-color: #d9d9d9;
13 ╵ ^
14
15assets/.../master.scss - Warning: Css Minimizer Plugin: >
16assets/.../master.scss:567:8: warning: Expected ":" but found "{"
17 567 │ circle {
18 ╵ ^
19
My Package.json is below:
1assets/.../variables.scss - Warning: Css Minimizer Plugin: > assets/.../variables.scss:6:0: warning: Unexpected "$"
2 6 │ $color-normal-gray:#8a8a8a;
3 ╵ ^
4
5assets/.../global.scss - Warning: Css Minimizer Plugin: >
6assets/.../global.scss:285:2: warning: Expected identifier but found "."
7 285 │ .dropdown-menu{
8 ╵ ^
9
10assets/.../global.scss - Warning: Css Minimizer Plugin: >
11assets/.../global.scss:255:6: warning: Expected identifier but found "*"
12 255 │ *background-color: #d9d9d9;
13 ╵ ^
14
15assets/.../master.scss - Warning: Css Minimizer Plugin: >
16assets/.../master.scss:567:8: warning: Expected ":" but found "{"
17 567 │ circle {
18 ╵ ^
19 "dependencies": {
20 "@angular/animations": "^12.2.3",
21 "@angular/cdk": "^12.2.2",
22 "@angular/common": "^12.2.3",
23 "@angular/compiler": "^12.2.3",
24 "@angular/core": "^12.2.3",
25 "@angular/forms": "^12.2.3",
26 "@angular/http": "^7.2.16",
27 "@angular/material": "^12.2.3",
28 "@angular/platform-browser": "^12.2.3",
29 "@angular/platform-browser-dynamic": "^12.2.3",
30 "@angular/router": "^12.2.3",
31 "@fortawesome/fontawesome-free": "^5.15.4",
32 "@ngrx/store": "^6.1.0",
33 "@okta/okta-angular": "^3.0.1",
34 "@okta/okta-auth-js": "^4.7.1",
35 "angular-datatables": "^0.6.4",
36 "angular-image-slider": "0.0.8",
37 "autobind-decorator": "^2.4.0",
38 "bootstrap": "^4.6.0",
39 "core-js": "^2.5.4",
40 "file-saver": "^2.0.2",
41 "gulp-cli": "^2.3.0",
42 "json-bigint": "^1.0.0",
43 "jsrsasign": "^10.3.0",
44 "lodash": "4.17.10",
45 "ng-simple-slideshow": "^1.2.4",
46 "ng2-scroll-to-el": "^1.2.1",
47 "ng2-search-filter": "^0.4.7",
48 "ngx-filter-pipe": "^2.1.2",
49 "ngx-logger": "3.3.11",
50 "ngx-order-pipe": "^2.0.1",
51 "ngx-pagination": "^3.2.0",
52 "pagination": "file:src/app/packages/pagination-0.0.1.tgz",
53 "rxjs": "7.3.0",
54 "rxjs-compat": "^6.3.2",
55 "sass": "^1.36.0",
56 "single-spa": "^5.9.2",
57 "single-spa-angular": "^5.0.2",
58 "systemjs": "^6.8.3",
59 "true-case-path": "^1.0.3",
60 "tslint": "^6.0.0",
61 "xlsx": "^0.17.1",
62 "zone.js": "~0.11.4"
63 },
64 "devDependencies": {
65 "@angular-builders/custom-webpack": "^12.1.1",
66 "@angular-devkit/build-angular": "^12.2.2",
67 "@angular-eslint/builder": "12.3.1",
68 "@angular-eslint/eslint-plugin": "12.3.1",
69 "@angular-eslint/eslint-plugin-template": "12.3.1",
70 "@angular-eslint/schematics": "12.3.1",
71 "@angular-eslint/template-parser": "12.3.1",
72 "@angular/cli": "^12.2.2",
73 "@angular/compiler-cli": "^12.2.3",
74 "@angular/language-service": "^12.2.3",
75 "@ng-bootstrap/ng-bootstrap": "^10.0.0",
76 "@types/bootstrap": "^4.1.2",
77 "@types/jasmine": "2.8.6",
78 "@types/jasminewd2": "2.0.3",
79 "@types/lodash": "4.14.110",
80 "@types/node": "14.6.2",
81 "@typescript-eslint/eslint-plugin": "4.28.2",
82 "@typescript-eslint/parser": "4.28.2",
83 "await": "^0.2.6",
84 "cheerio": "^1.0.0-rc.2",
85 "codelyzer": "~4.2.1",
86 "eslint": "^7.26.0",
87 "font-awesome": "^4.7.0",
88 "fs-promise": "^2.0.3",
89 "gulp": "^4.0.2",
90 "gulp-inline-css": "^3.3.0",
91 "gulp-inline-source": "^4.0.0",
92 "htmlhint-ng2": "0.0.13",
93 "husky": "^1.3.1",
94 "jasmine-core": "~2.99.1",
95 "jasmine-spec-reporter": "~4.2.1",
96 "karma": "^6.3.4",
97 "karma-chrome-launcher": "^2.2.0",
98 "karma-coverage-istanbul-reporter": "^2.1.1",
99 "karma-jasmine": "~1.1.1",
100 "karma-jasmine-html-reporter": "^0.2.2",
101 "karma-junit-reporter": "^1.2.0",
102 "mediaquery-text": "1.0.7",
103 "ng-bullet": "^1.0.3",
104 "protractor": "^5.4.2",
105 "puppeteer": "^1.14.0",
106 "sonar-scanner": "^3.1.0",
107 "ts-node": "~5.0.1",
108 "tslint": "~5.9.1",
109 "tslint-sonarts": "^1.9.0",
110 "typescript": "^4.3.5"
111 }
112
ANSWER
Answered 2021-Sep-08 at 10:30I had the same problem. You should change the import of 'assets/.../variables.scss' to './assets/.../variables.scss'. In my case it was in styles.scss but it can be in every .scss file.
QUESTION
rxjs 7 update - Subject - Expected 1 arguments, but got 0
Asked 2021-Nov-19 at 10:13I updated rxjs from version 6.x.x to 7.x.x, but following error appeared:
Error in src/app/app.component.ts (12:19) Expected 1 arguments, but got 0.
when trying to next
an empty value to the Subject
1destroy$ = new Subject();
2
3constructor() {
4 this.destroy$.next(); // <-- Expected 1 arguments, but got 0.
5}
6
ANSWER
Answered 2021-Jul-30 at 12:42tl;dr:
Either typecast it with void
:
1destroy$ = new Subject();
2
3constructor() {
4 this.destroy$.next(); // <-- Expected 1 arguments, but got 0.
5}
6new Subject<void>();
7
or pass a fake value:
1destroy$ = new Subject();
2
3constructor() {
4 this.destroy$.next(); // <-- Expected 1 arguments, but got 0.
5}
6new Subject<void>();
7this.destroy$.next(true);
8
Rxjs 7 changes
After checking the changelog and several github issues about this situation,
Subject: resolve issue where Subject constructor errantly allowed an argument (#5476) (e1d35dc)
Subject: no default generic (e678e81)
Changelog 7.0.0-beta.1 and the commit where empty value is removed from the tests
I realized that the solution was to either provide a value or simply typecast the Subject
with <void>
as in destroy$ = new Subject<void>()
if you want to next
it with an empty value.
Community Discussions contain sources that include Stack Exchange Network