mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 04:43:03 -05:00
feat: challage 38 - rxjs catch error
This commit is contained in:
@@ -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 ✨
|
||||
|
||||
|
||||
36
apps/rxjs-catch-error/.eslintrc.json
Normal file
36
apps/rxjs-catch-error/.eslintrc.json
Normal file
@@ -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": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
13
apps/rxjs-catch-error/README.md
Normal file
13
apps/rxjs-catch-error/README.md
Normal file
@@ -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/).
|
||||
22
apps/rxjs-catch-error/jest.config.ts
Normal file
22
apps/rxjs-catch-error/jest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'rxjs-catch-error',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
coverageDirectory: '../../coverage/apps/rxjs-catch-error',
|
||||
transform: {
|
||||
'^.+\\.(ts|mjs|js|html)$': [
|
||||
'jest-preset-angular',
|
||||
{
|
||||
tsconfig: '<rootDir>/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',
|
||||
],
|
||||
};
|
||||
95
apps/rxjs-catch-error/project.json
Normal file
95
apps/rxjs-catch-error/project.json
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
apps/rxjs-catch-error/src/app/app.component.spec.ts
Normal file
8
apps/rxjs-catch-error/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { render } from '@testing-library/angular';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
test('...', async () => {
|
||||
await render(AppComponent);
|
||||
});
|
||||
});
|
||||
79
apps/rxjs-catch-error/src/app/app.component.ts
Normal file
79
apps/rxjs-catch-error/src/app/app.component.ts
Normal file
@@ -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: `
|
||||
<div class="form-container">
|
||||
<span>Posible values: posts, comments, albums, photos, todos, users</span>
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<input #inputRef type="text" placeholder="Enter text" />
|
||||
<button #buttonRef>Fetch</button>
|
||||
</div>
|
||||
<div class="form-container">
|
||||
{{ response | json }}
|
||||
</div>
|
||||
`,
|
||||
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'),
|
||||
});
|
||||
}
|
||||
}
|
||||
6
apps/rxjs-catch-error/src/app/app.config.ts
Normal file
6
apps/rxjs-catch-error/src/app/app.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [importProvidersFrom(HttpClientModule)],
|
||||
};
|
||||
0
apps/rxjs-catch-error/src/assets/.gitkeep
Normal file
0
apps/rxjs-catch-error/src/assets/.gitkeep
Normal file
BIN
apps/rxjs-catch-error/src/favicon.ico
Normal file
BIN
apps/rxjs-catch-error/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
13
apps/rxjs-catch-error/src/index.html
Normal file
13
apps/rxjs-catch-error/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>rxjs-catch-error</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
7
apps/rxjs-catch-error/src/main.ts
Normal file
7
apps/rxjs-catch-error/src/main.ts
Normal file
@@ -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)
|
||||
);
|
||||
5
apps/rxjs-catch-error/src/styles.scss
Normal file
5
apps/rxjs-catch-error/src/styles.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
2
apps/rxjs-catch-error/src/test-setup.ts
Normal file
2
apps/rxjs-catch-error/src/test-setup.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import 'jest-preset-angular/setup-jest';
|
||||
14
apps/rxjs-catch-error/tailwind.config.js
Normal file
14
apps/rxjs-catch-error/tailwind.config.js
Normal file
@@ -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: [],
|
||||
};
|
||||
10
apps/rxjs-catch-error/tsconfig.app.json
Normal file
10
apps/rxjs-catch-error/tsconfig.app.json
Normal file
@@ -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"]
|
||||
}
|
||||
7
apps/rxjs-catch-error/tsconfig.editor.json
Normal file
7
apps/rxjs-catch-error/tsconfig.editor.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
}
|
||||
}
|
||||
32
apps/rxjs-catch-error/tsconfig.json
Normal file
32
apps/rxjs-catch-error/tsconfig.json
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
15
apps/rxjs-catch-error/tsconfig.spec.json
Normal file
15
apps/rxjs-catch-error/tsconfig.spec.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"total": 37,
|
||||
"🟢": 13,
|
||||
"total": 38,
|
||||
"🟢": 14,
|
||||
"🟠": 117,
|
||||
"🔴": 207
|
||||
}
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
<div class="chip">Challenge #37</div>
|
||||
|
||||
43
docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md
Normal file
43
docs/src/content/docs/challenges/rxjs/38-rxjs-catch-error.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: 🟢 catchError
|
||||
description: Challenge 38 is about learning error handling with catchError rxjs operator
|
||||
sidebar:
|
||||
order: 14
|
||||
badge: New
|
||||
---
|
||||
|
||||
<div class="chip">Challenge #38</div>
|
||||
|
||||
## 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 <b>Answer:38</b>.
|
||||
:::
|
||||
|
||||
<div class="article-footer">
|
||||
<a
|
||||
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A38+label%3Aanswer"
|
||||
alt="catchError community solutions">
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A38+label%3A"answer+author"'
|
||||
alt="catchError solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
</div>
|
||||
@@ -23,8 +23,8 @@ hero:
|
||||
import { Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
<CardGrid>
|
||||
<Card title="37 Challenges">
|
||||
This repository gathers 37 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
|
||||
<Card title="38 Challenges">
|
||||
This repository gathers 38 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
|
||||
These challenges resolve around real-life issues or specific features to elevate your skills.
|
||||
</Card>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user