From ccb3b106dcd41ba453b234dc21c677d4fd7d2e32 Mon Sep 17 00:00:00 2001 From: Devesh Date: Sat, 14 Oct 2023 01:24:27 +0530 Subject: [PATCH 1/5] feat: challage 38 - rxjs catch error --- README.md | 2 +- apps/rxjs-catch-error/.eslintrc.json | 36 +++++++ apps/rxjs-catch-error/README.md | 13 +++ apps/rxjs-catch-error/jest.config.ts | 22 ++++ apps/rxjs-catch-error/project.json | 95 ++++++++++++++++++ .../src/app/app.component.spec.ts | 8 ++ .../rxjs-catch-error/src/app/app.component.ts | 79 +++++++++++++++ apps/rxjs-catch-error/src/app/app.config.ts | 6 ++ apps/rxjs-catch-error/src/assets/.gitkeep | 0 apps/rxjs-catch-error/src/favicon.ico | Bin 0 -> 15086 bytes apps/rxjs-catch-error/src/index.html | 13 +++ apps/rxjs-catch-error/src/main.ts | 7 ++ apps/rxjs-catch-error/src/styles.scss | 5 + apps/rxjs-catch-error/src/test-setup.ts | 2 + apps/rxjs-catch-error/tailwind.config.js | 14 +++ apps/rxjs-catch-error/tsconfig.app.json | 10 ++ apps/rxjs-catch-error/tsconfig.editor.json | 7 ++ apps/rxjs-catch-error/tsconfig.json | 32 ++++++ apps/rxjs-catch-error/tsconfig.spec.json | 15 +++ challenge-number.json | 4 +- .../angular-performance/37-ngfor-biglist.md | 1 - .../challenges/rxjs/38-rxjs-catch-error.md | 43 ++++++++ docs/src/content/docs/index.mdx | 4 +- 23 files changed, 412 insertions(+), 6 deletions(-) create mode 100644 apps/rxjs-catch-error/.eslintrc.json create mode 100644 apps/rxjs-catch-error/README.md create mode 100644 apps/rxjs-catch-error/jest.config.ts create mode 100644 apps/rxjs-catch-error/project.json create mode 100644 apps/rxjs-catch-error/src/app/app.component.spec.ts create mode 100644 apps/rxjs-catch-error/src/app/app.component.ts create mode 100644 apps/rxjs-catch-error/src/app/app.config.ts create mode 100644 apps/rxjs-catch-error/src/assets/.gitkeep create mode 100644 apps/rxjs-catch-error/src/favicon.ico create mode 100644 apps/rxjs-catch-error/src/index.html create mode 100644 apps/rxjs-catch-error/src/main.ts create mode 100644 apps/rxjs-catch-error/src/styles.scss create mode 100644 apps/rxjs-catch-error/src/test-setup.ts create mode 100644 apps/rxjs-catch-error/tailwind.config.js create mode 100644 apps/rxjs-catch-error/tsconfig.app.json create mode 100644 apps/rxjs-catch-error/tsconfig.editor.json create mode 100644 apps/rxjs-catch-error/tsconfig.json create mode 100644 apps/rxjs-catch-error/tsconfig.spec.json create mode 100644 docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md diff --git a/README.md b/README.md index 136070d..a4ddb58 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f ## Challenges -Check [all 37 challenges](https://angular-challenges.vercel.app/) +Check [all 38 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ diff --git a/apps/rxjs-catch-error/.eslintrc.json b/apps/rxjs-catch-error/.eslintrc.json new file mode 100644 index 0000000..b428c22 --- /dev/null +++ b/apps/rxjs-catch-error/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + }, + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/rxjs-catch-error/README.md b/apps/rxjs-catch-error/README.md new file mode 100644 index 0000000..d1808fd --- /dev/null +++ b/apps/rxjs-catch-error/README.md @@ -0,0 +1,13 @@ +# catchError + +> Author: Devesh Chaudhari + +### Run Application + +```bash +npx nx serve rxjs-catch-error +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/38-catch-error/). diff --git a/apps/rxjs-catch-error/jest.config.ts b/apps/rxjs-catch-error/jest.config.ts new file mode 100644 index 0000000..0f2fbb2 --- /dev/null +++ b/apps/rxjs-catch-error/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'rxjs-catch-error', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../coverage/apps/rxjs-catch-error', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/rxjs-catch-error/project.json b/apps/rxjs-catch-error/project.json new file mode 100644 index 0000000..7c191a9 --- /dev/null +++ b/apps/rxjs-catch-error/project.json @@ -0,0 +1,95 @@ +{ + "name": "rxjs-catch-error", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/rxjs-catch-error/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/rxjs-catch-error", + "index": "apps/rxjs-catch-error/src/index.html", + "main": "apps/rxjs-catch-error/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/rxjs-catch-error/tsconfig.app.json", + "assets": [ + "apps/rxjs-catch-error/src/favicon.ico", + "apps/rxjs-catch-error/src/assets" + ], + "styles": ["apps/rxjs-catch-error/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "rxjs-catch-error:build:production" + }, + "development": { + "browserTarget": "rxjs-catch-error:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "rxjs-catch-error:build" + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "apps/rxjs-catch-error/**/*.ts", + "apps/rxjs-catch-error/**/*.html" + ] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "apps/rxjs-catch-error/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/rxjs-catch-error/src/app/app.component.spec.ts b/apps/rxjs-catch-error/src/app/app.component.spec.ts new file mode 100644 index 0000000..3905d62 --- /dev/null +++ b/apps/rxjs-catch-error/src/app/app.component.spec.ts @@ -0,0 +1,8 @@ +import { render } from '@testing-library/angular'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + test('...', async () => { + await render(AppComponent); + }); +}); diff --git a/apps/rxjs-catch-error/src/app/app.component.ts b/apps/rxjs-catch-error/src/app/app.component.ts new file mode 100644 index 0000000..17117e4 --- /dev/null +++ b/apps/rxjs-catch-error/src/app/app.component.ts @@ -0,0 +1,79 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { concatMap, fromEvent, map } from 'rxjs'; +import { CommonModule } from '@angular/common'; + +@Component({ + standalone: true, + imports: [CommonModule], + selector: 'app-root', + template: ` +
+ Posible values: posts, comments, albums, photos, todos, users +
+
+ + +
+
+ {{ response | json }} +
+ `, + styles: [ + ` + body { + font-family: Arial, sans-serif; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + margin: 0; + } + .form-container { + text-align: center; + } + input { + padding: 8px; + margin-right: 8px; + border: 1px solid #ccc; + border-radius: 4px; + } + button { + padding: 8px 16px; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; + } + `, + ], +}) +export class AppComponent { + @ViewChild('buttonRef', { static: true }) buttonRef!: ElementRef; + @ViewChild('inputRef', { static: true }) inputRef!: ElementRef; + response: unknown; + constructor(private http: HttpClient) {} + + ngOnInit() { + const buttonClick$ = fromEvent(this.buttonRef.nativeElement, 'click'); + buttonClick$ + .pipe( + map(() => this.inputRef.nativeElement.value), + concatMap((value) => + this.http.get(`https://jsonplaceholder.typicode.com/${value}/1`) + ) + ) + .subscribe({ + next: (value) => { + console.log(value); + this.response = value; + }, + error: (error) => { + console.log(error); + this.response = error; + }, + complete: () => console.log('done'), + }); + } +} diff --git a/apps/rxjs-catch-error/src/app/app.config.ts b/apps/rxjs-catch-error/src/app/app.config.ts new file mode 100644 index 0000000..610704b --- /dev/null +++ b/apps/rxjs-catch-error/src/app/app.config.ts @@ -0,0 +1,6 @@ +import { ApplicationConfig, importProvidersFrom } from '@angular/core'; +import { HttpClientModule } from '@angular/common/http'; + +export const appConfig: ApplicationConfig = { + providers: [importProvidersFrom(HttpClientModule)], +}; diff --git a/apps/rxjs-catch-error/src/assets/.gitkeep b/apps/rxjs-catch-error/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/rxjs-catch-error/src/favicon.ico b/apps/rxjs-catch-error/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 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 + + + + rxjs-catch-error + + + + + + + + diff --git a/apps/rxjs-catch-error/src/main.ts b/apps/rxjs-catch-error/src/main.ts new file mode 100644 index 0000000..514c89a --- /dev/null +++ b/apps/rxjs-catch-error/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err) +); diff --git a/apps/rxjs-catch-error/src/styles.scss b/apps/rxjs-catch-error/src/styles.scss new file mode 100644 index 0000000..77e408a --- /dev/null +++ b/apps/rxjs-catch-error/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/rxjs-catch-error/src/test-setup.ts b/apps/rxjs-catch-error/src/test-setup.ts new file mode 100644 index 0000000..15de72a --- /dev/null +++ b/apps/rxjs-catch-error/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/rxjs-catch-error/tailwind.config.js b/apps/rxjs-catch-error/tailwind.config.js new file mode 100644 index 0000000..38183db --- /dev/null +++ b/apps/rxjs-catch-error/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/rxjs-catch-error/tsconfig.app.json b/apps/rxjs-catch-error/tsconfig.app.json new file mode 100644 index 0000000..fff4a41 --- /dev/null +++ b/apps/rxjs-catch-error/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/rxjs-catch-error/tsconfig.editor.json b/apps/rxjs-catch-error/tsconfig.editor.json new file mode 100644 index 0000000..8ae117d --- /dev/null +++ b/apps/rxjs-catch-error/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/rxjs-catch-error/tsconfig.json b/apps/rxjs-catch-error/tsconfig.json new file mode 100644 index 0000000..e01cf19 --- /dev/null +++ b/apps/rxjs-catch-error/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/rxjs-catch-error/tsconfig.spec.json b/apps/rxjs-catch-error/tsconfig.spec.json new file mode 100644 index 0000000..1a4817a --- /dev/null +++ b/apps/rxjs-catch-error/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/challenge-number.json b/challenge-number.json index 14d6f15..55abd21 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,6 +1,6 @@ { - "total": 37, - "🟢": 13, + "total": 38, + "🟢": 14, "🟠": 117, "🔴": 207 } diff --git a/docs/src/content/docs/challenges/angular-performance/37-ngfor-biglist.md b/docs/src/content/docs/challenges/angular-performance/37-ngfor-biglist.md index 84e28f3..6cc1f48 100644 --- a/docs/src/content/docs/challenges/angular-performance/37-ngfor-biglist.md +++ b/docs/src/content/docs/challenges/angular-performance/37-ngfor-biglist.md @@ -3,7 +3,6 @@ title: 🟠 Optimize Big List description: Challenge 37 is about learning how virtualization optimize big list rendering sidebar: order: 117 - badge: New ---
Challenge #37
diff --git a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md new file mode 100644 index 0000000..c1d7f58 --- /dev/null +++ b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md @@ -0,0 +1,43 @@ +--- +title: 🟢 catchError +description: Challenge 38 is about learning error handling with catchError rxjs operator +sidebar: + order: 14 + badge: New +--- + +
Challenge #38
+ +## Information + +In this application, we will learn the correct placement of a catchError operator. If wrongly placed, the overall subscription will get completed. And we will not be able to send more requests. Aim is to preserve overall subscription, by taking care of error notification from inner observables. +Possible correct values for which we should get a success response are posts, comments, albums, photos, todos, users + +## Statement + +Handle the error without completion of the subscription. + +## Constraints + +## Users should be able to console log value/error each time clicks on the fetch button. + +:::note +Start the project by running: `npx nx serve rxjs-catch-error`. +::: + +:::tip[Reminder] +Your PR title must start with Answer:38. +::: + + diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 80e2ce9..40c476e 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -23,8 +23,8 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; - - This repository gathers 37 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. + + This repository gathers 38 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. These challenges resolve around real-life issues or specific features to elevate your skills. From 7e4c75061328241435da9d63b0c5799643fba0f8 Mon Sep 17 00:00:00 2001 From: Devesh Date: Sat, 14 Oct 2023 10:36:52 +0530 Subject: [PATCH 2/5] style: cap response div --- apps/rxjs-catch-error/src/app/app.component.ts | 15 ++++++++++++--- .../docs/challenges/rxjs/38-rxjs-catch-error.md | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/rxjs-catch-error/src/app/app.component.ts b/apps/rxjs-catch-error/src/app/app.component.ts index 17117e4..aae88b2 100644 --- a/apps/rxjs-catch-error/src/app/app.component.ts +++ b/apps/rxjs-catch-error/src/app/app.component.ts @@ -1,6 +1,6 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { concatMap, fromEvent, map } from 'rxjs'; +import { Observable, Subscription, concatMap, fromEvent, map } from 'rxjs'; import { CommonModule } from '@angular/common'; @Component({ @@ -9,13 +9,15 @@ import { CommonModule } from '@angular/common'; selector: 'app-root', template: `
- Posible values: posts, comments, albums, photos, todos, users + possible values: posts, comments, albums, photos, todos, users
-
+
{{ response | json }}
`, @@ -46,6 +48,13 @@ import { CommonModule } from '@angular/common'; border-radius: 4px; cursor: pointer; } + .response { + margin-left: 25%; + margin-top: 2%; + width: 50%; + text-align: center; + border: 1px solid #ccc; + } `, ], }) diff --git a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md index c1d7f58..275de5e 100644 --- a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md +++ b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md @@ -19,7 +19,7 @@ Handle the error without completion of the subscription. ## Constraints -## Users should be able to console log value/error each time clicks on the fetch button. +Users should be able to console log value/error each time clicks on the fetch button. :::note Start the project by running: `npx nx serve rxjs-catch-error`. From 967ba0f8cd40a4c446bddffdbc0abb179030648e Mon Sep 17 00:00:00 2001 From: Devesh Date: Mon, 16 Oct 2023 15:39:01 +0530 Subject: [PATCH 3/5] refactor: use form, and update readme --- .../src/app/app.component.css | 32 +++++++++ .../rxjs-catch-error/src/app/app.component.ts | 71 ++++++------------- .../challenges/rxjs/38-rxjs-catch-error.md | 19 +++-- 3 files changed, 65 insertions(+), 57 deletions(-) create mode 100644 apps/rxjs-catch-error/src/app/app.component.css diff --git a/apps/rxjs-catch-error/src/app/app.component.css b/apps/rxjs-catch-error/src/app/app.component.css new file mode 100644 index 0000000..e4064b2 --- /dev/null +++ b/apps/rxjs-catch-error/src/app/app.component.css @@ -0,0 +1,32 @@ +body { + font-family: Arial, sans-serif; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + margin: 0; + } + .form-container { + text-align: center; + } + input { + padding: 8px; + margin-right: 8px; + border: 1px solid #ccc; + border-radius: 4px; + } + button { + padding: 8px 16px; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; + } + .response { + margin-left: 25%; + margin-top: 2%; + width: 50%; + text-align: center; + border: 1px solid #ccc; + } \ No newline at end of file diff --git a/apps/rxjs-catch-error/src/app/app.component.ts b/apps/rxjs-catch-error/src/app/app.component.ts index aae88b2..c7dfb0f 100644 --- a/apps/rxjs-catch-error/src/app/app.component.ts +++ b/apps/rxjs-catch-error/src/app/app.component.ts @@ -1,11 +1,13 @@ -import { Component, ElementRef, ViewChild } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Observable, Subscription, concatMap, fromEvent, map } from 'rxjs'; +import { Component, DestroyRef, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { Subject, concatMap, map } from 'rxjs'; @Component({ standalone: true, - imports: [CommonModule], + imports: [CommonModule, FormsModule], selector: 'app-root', template: `
@@ -13,62 +15,31 @@ import { CommonModule } from '@angular/common'; >possible values: posts, comments, albums, photos, todos, users
-
- - -
+
+ + +
{{ response | json }}
`, - styles: [ - ` - body { - font-family: Arial, sans-serif; - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - margin: 0; - } - .form-container { - text-align: center; - } - input { - padding: 8px; - margin-right: 8px; - border: 1px solid #ccc; - border-radius: 4px; - } - button { - padding: 8px 16px; - background-color: #007bff; - color: #fff; - border: none; - border-radius: 4px; - cursor: pointer; - } - .response { - margin-left: 25%; - margin-top: 2%; - width: 50%; - text-align: center; - border: 1px solid #ccc; - } - `, - ], + styleUrls: ['./app.component.css'], }) export class AppComponent { - @ViewChild('buttonRef', { static: true }) buttonRef!: ElementRef; - @ViewChild('inputRef', { static: true }) inputRef!: ElementRef; + submit$$ = new Subject(); + input = ''; response: unknown; + private destroyRef = inject(DestroyRef); constructor(private http: HttpClient) {} - ngOnInit() { - const buttonClick$ = fromEvent(this.buttonRef.nativeElement, 'click'); - buttonClick$ + this.submit$$ .pipe( - map(() => this.inputRef.nativeElement.value), + takeUntilDestroyed(this.destroyRef), + map(() => this.input), concatMap((value) => this.http.get(`https://jsonplaceholder.typicode.com/${value}/1`) ) diff --git a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md index 275de5e..cf9edb9 100644 --- a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md +++ b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md @@ -1,6 +1,6 @@ --- title: 🟢 catchError -description: Challenge 38 is about learning error handling with catchError rxjs operator +description: Challenge 38 is about learning obervable completion. sidebar: order: 14 badge: New @@ -8,18 +8,23 @@ sidebar:
Challenge #38
-## Information +## How to Use the Application -In this application, we will learn the correct placement of a catchError operator. If wrongly placed, the overall subscription will get completed. And we will not be able to send more requests. Aim is to preserve overall subscription, by taking care of error notification from inner observables. -Possible correct values for which we should get a success response are posts, comments, albums, photos, todos, users +Our application features a form with a text input box and a "Fetch" button. Upon clicking the "Fetch" button, data is retrieved from a [free API](https://jsonplaceholder.typicode.com/){:target="\_blank"}. -## Statement +The correct values for a successful response are limited to: posts, comments, albums, photos, todos, and users. Any other values will result in an error response. -Handle the error without completion of the subscription. +## Bug + +A bug has been identified in our application. Users are only able to successfully fetch data until an invalid request is sent. Once an error response is received, users are unable to send additional requests. + +## Learnings + +This application provides an opportunity to understand the correct placement of a `catchError` operator. If placed incorrectly, the overall subscription will be completed, preventing users from sending more requests. The goal is to preserve the overall subscription by handling error notifications from inner observables appropriately. ## Constraints -Users should be able to console log value/error each time clicks on the fetch button. +Users should be able to log the value/error each time they click the "Fetch" button. :::note Start the project by running: `npx nx serve rxjs-catch-error`. From b62c151794e51e134684dc031a08cbb423ef7d54 Mon Sep 17 00:00:00 2001 From: Devesh Date: Tue, 17 Oct 2023 08:38:06 +0530 Subject: [PATCH 4/5] docs: improve readme file --- .../rxjs-catch-error/src/app/app.component.ts | 4 +- .../challenges/rxjs/38-rxjs-catch-error.md | 39 ++++++++----------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/apps/rxjs-catch-error/src/app/app.component.ts b/apps/rxjs-catch-error/src/app/app.component.ts index c7dfb0f..6974c93 100644 --- a/apps/rxjs-catch-error/src/app/app.component.ts +++ b/apps/rxjs-catch-error/src/app/app.component.ts @@ -38,11 +38,11 @@ export class AppComponent { ngOnInit() { this.submit$$ .pipe( - takeUntilDestroyed(this.destroyRef), map(() => this.input), concatMap((value) => this.http.get(`https://jsonplaceholder.typicode.com/${value}/1`) - ) + ), + takeUntilDestroyed(this.destroyRef) ) .subscribe({ next: (value) => { diff --git a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md index cf9edb9..8fd668f 100644 --- a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md +++ b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md @@ -1,12 +1,22 @@ --- title: 🟢 catchError -description: Challenge 38 is about learning obervable completion. +description: Challenge 38 is about learning obervable +completion. +Author: Devesh Chaudhari +command: rxjs-catch-error +challengeNumber: 38 sidebar: order: 14 badge: New --- -
Challenge #38
+:::note +WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue. +::: + +## Information + +--- ## How to Use the Application @@ -22,27 +32,10 @@ A bug has been identified in our application. Users are only able to successfull This application provides an opportunity to understand the correct placement of a `catchError` operator. If placed incorrectly, the overall subscription will be completed, preventing users from sending more requests. The goal is to preserve the overall subscription by handling error notifications from inner observables appropriately. +## Statement + +The goal is to use the catchError operator to handle error management inside your Rxjs stream. + ## Constraints Users should be able to log the value/error each time they click the "Fetch" button. - -:::note -Start the project by running: `npx nx serve rxjs-catch-error`. -::: - -:::tip[Reminder] -Your PR title must start with Answer:38. -::: - - From af2189478374981c2952f01a6f24fd28b489ce47 Mon Sep 17 00:00:00 2001 From: thomas Date: Tue, 17 Oct 2023 08:41:01 +0200 Subject: [PATCH 5/5] fix(*): fix last error --- .../docs/challenges/rxjs/38-rxjs-catch-error.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md index 8fd668f..dec6c92 100644 --- a/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md +++ b/docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md @@ -1,7 +1,6 @@ --- title: 🟢 catchError -description: Challenge 38 is about learning obervable -completion. +description: Challenge 38 is about learning obervable completion. Author: Devesh Chaudhari command: rxjs-catch-error challengeNumber: 38 @@ -10,27 +9,21 @@ sidebar: badge: New --- -:::note -WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue. -::: - ## Information ---- - -## How to Use the Application +### How to Use the Application Our application features a form with a text input box and a "Fetch" button. Upon clicking the "Fetch" button, data is retrieved from a [free API](https://jsonplaceholder.typicode.com/){:target="\_blank"}. The correct values for a successful response are limited to: posts, comments, albums, photos, todos, and users. Any other values will result in an error response. -## Bug +### Bug A bug has been identified in our application. Users are only able to successfully fetch data until an invalid request is sent. Once an error response is received, users are unable to send additional requests. -## Learnings +### Learnings -This application provides an opportunity to understand the correct placement of a `catchError` operator. If placed incorrectly, the overall subscription will be completed, preventing users from sending more requests. The goal is to preserve the overall subscription by handling error notifications from inner observables appropriately. +This application provides an opportunity to understand the correct placement of a [`catchError`](https://rxjs.dev/api/operators/catchError) operator. If placed incorrectly, the overall subscription will be completed, preventing users from sending more requests. The goal is to preserve the overall subscription by handling error notifications from inner observables appropriately. ## Statement