From 0f4f14c3518e310f7203ae01e5350f781598e0d6 Mon Sep 17 00:00:00 2001 From: Wandrille Date: Fri, 9 Feb 2024 09:25:05 +0100 Subject: [PATCH 001/361] feat: challenge 45 React in Angular Add new challenge: React in Angular. --- README.md | 2 +- apps/angular/react-in-angular/.eslintrc.json | 36 ++++++++ apps/angular/react-in-angular/README.md | 13 +++ apps/angular/react-in-angular/jest.config.ts | 22 +++++ apps/angular/react-in-angular/project.json | 80 ++++++++++++++++++ .../react-in-angular/src/app/app.component.ts | 62 ++++++++++++++ .../react-in-angular/src/app/app.config.ts | 5 ++ .../src/app/react/ReactPost.tsx | 27 ++++++ .../src/app/react/post.component.ts | 17 ++++ .../react-in-angular/src/assets/.gitkeep | 0 apps/angular/react-in-angular/src/favicon.ico | Bin 0 -> 15086 bytes apps/angular/react-in-angular/src/index.html | 13 +++ apps/angular/react-in-angular/src/main.ts | 7 ++ apps/angular/react-in-angular/src/styles.scss | 5 ++ .../react-in-angular/src/test-setup.ts | 2 + .../react-in-angular/tailwind.config.js | 14 +++ .../react-in-angular/tsconfig.app.json | 10 +++ .../react-in-angular/tsconfig.editor.json | 7 ++ apps/angular/react-in-angular/tsconfig.json | 33 ++++++++ .../react-in-angular/tsconfig.spec.json | 15 ++++ challenge-number.json | 4 +- .../challenges/angular/45-react-in-angular.md | 76 +++++++++++++++++ docs/src/content/docs/es/index.mdx | 11 +-- docs/src/content/docs/fr/index.mdx | 8 +- docs/src/content/docs/index.mdx | 9 +- docs/src/content/docs/pt/index.mdx | 13 +-- docs/src/content/docs/ru/index.mdx | 31 ++++--- 27 files changed, 485 insertions(+), 37 deletions(-) create mode 100644 apps/angular/react-in-angular/.eslintrc.json create mode 100644 apps/angular/react-in-angular/README.md create mode 100644 apps/angular/react-in-angular/jest.config.ts create mode 100644 apps/angular/react-in-angular/project.json create mode 100644 apps/angular/react-in-angular/src/app/app.component.ts create mode 100644 apps/angular/react-in-angular/src/app/app.config.ts create mode 100644 apps/angular/react-in-angular/src/app/react/ReactPost.tsx create mode 100644 apps/angular/react-in-angular/src/app/react/post.component.ts create mode 100644 apps/angular/react-in-angular/src/assets/.gitkeep create mode 100644 apps/angular/react-in-angular/src/favicon.ico create mode 100644 apps/angular/react-in-angular/src/index.html create mode 100644 apps/angular/react-in-angular/src/main.ts create mode 100644 apps/angular/react-in-angular/src/styles.scss create mode 100644 apps/angular/react-in-angular/src/test-setup.ts create mode 100644 apps/angular/react-in-angular/tailwind.config.js create mode 100644 apps/angular/react-in-angular/tsconfig.app.json create mode 100644 apps/angular/react-in-angular/tsconfig.editor.json create mode 100644 apps/angular/react-in-angular/tsconfig.json create mode 100644 apps/angular/react-in-angular/tsconfig.spec.json create mode 100644 docs/src/content/docs/challenges/angular/45-react-in-angular.md diff --git a/README.md b/README.md index 1e43bdfef..de881440c 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 44 challenges](https://angular-challenges.vercel.app/) +Check [all 45 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ diff --git a/apps/angular/react-in-angular/.eslintrc.json b/apps/angular/react-in-angular/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/angular/react-in-angular/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/react-in-angular/README.md b/apps/angular/react-in-angular/README.md new file mode 100644 index 000000000..0a8679ac4 --- /dev/null +++ b/apps/angular/react-in-angular/README.md @@ -0,0 +1,13 @@ +# React in angular + +> author: wandrille-guesdon + +### Run Application + +```bash +npx nx serve angular-react-in-angular +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/45-react-in-angular/). diff --git a/apps/angular/react-in-angular/jest.config.ts b/apps/angular/react-in-angular/jest.config.ts new file mode 100644 index 000000000..92d5f2583 --- /dev/null +++ b/apps/angular/react-in-angular/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-react-in-angular', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/react-in-angular', + 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/angular/react-in-angular/project.json b/apps/angular/react-in-angular/project.json new file mode 100644 index 000000000..8153ec8d3 --- /dev/null +++ b/apps/angular/react-in-angular/project.json @@ -0,0 +1,80 @@ +{ + "name": "angular-react-in-angular", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/react-in-angular/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/react-in-angular", + "index": "apps/angular/react-in-angular/src/index.html", + "browser": "apps/angular/react-in-angular/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/react-in-angular/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/react-in-angular/src/favicon.ico", + "apps/angular/react-in-angular/src/assets" + ], + "styles": ["apps/angular/react-in-angular/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-react-in-angular:build:production" + }, + "development": { + "buildTarget": "angular-react-in-angular:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-react-in-angular:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "apps/angular/react-in-angular/jest.config.ts" + } + } + } +} diff --git a/apps/angular/react-in-angular/src/app/app.component.ts b/apps/angular/react-in-angular/src/app/app.component.ts new file mode 100644 index 000000000..a914cc65f --- /dev/null +++ b/apps/angular/react-in-angular/src/app/app.component.ts @@ -0,0 +1,62 @@ +import { Component, signal } from '@angular/core'; +import { PostComponent } from './react/post.component'; + +type Post = { title: string; description: string }; + +@Component({ + standalone: true, + imports: [PostComponent], + selector: 'app-root', + template: ` +
+
+ @for (post of posts; track post.title) { +
+ +
+ } +
+
+ Selected Post: + + {{ selectedPost()?.title ?? '-' }} + +
+
+ `, + styles: [''], +}) +export class AppComponent { + readonly posts = [ + { + title: 'A Deep Dive into Angular', + description: + "Explore Angular's core features, its evolution, and best practices in development for creating dynamic, efficient web applications in our comprehensive guide.", + pictureLink: + 'https://images.unsplash.com/photo-1471958680802-1345a694ba6d', + }, + { + title: 'The Perfect Combination', + description: + 'Unveil the power of combining Angular & React in web development, maximizing efficiency and flexibility for building scalable, sophisticated applications.', + pictureLink: + 'https://images.unsplash.com/photo-1518717202715-9fa9d099f58a', + }, + { + title: 'Taking Angular to the Next Level', + description: + "Discover how integrating React with Angular elevates web development, blending Angular's structure with React's UI prowess for advanced applications.", + pictureLink: + 'https://images.unsplash.com/photo-1532103050105-860af53bc6aa', + }, + ]; + + readonly selectedPost = signal(null); + + selectPost(post: Post) { + this.selectedPost.set(post); + } +} diff --git a/apps/angular/react-in-angular/src/app/app.config.ts b/apps/angular/react-in-angular/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/angular/react-in-angular/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/angular/react-in-angular/src/app/react/ReactPost.tsx b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx new file mode 100644 index 000000000..6ff7b4df4 --- /dev/null +++ b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx @@ -0,0 +1,27 @@ +// import React from 'react'; + +export default function ReactPost(props: { + title?: string, + description?: string, + pictureLink?: string, + selected?: boolean, + handleClick: () => void +}) { + return ( +
+
+ {props.title} +
+
{props.title}
+

+ {props.description} +

+ +
+
+
+ ); +} diff --git a/apps/angular/react-in-angular/src/app/react/post.component.ts b/apps/angular/react-in-angular/src/app/react/post.component.ts new file mode 100644 index 000000000..2a35eaca6 --- /dev/null +++ b/apps/angular/react-in-angular/src/app/react/post.component.ts @@ -0,0 +1,17 @@ +import { Component, EventEmitter, input, Output } from '@angular/core'; + +type Post = { title: string; description: string; pictureLink: string }; + +@Component({ + standalone: true, + selector: 'app-post', + template: ` +
+ `, + styles: [''], +}) +export class PostComponent { + post = input(undefined); + isSelected = input(false); + @Output() selectPost = new EventEmitter(); +} diff --git a/apps/angular/react-in-angular/src/assets/.gitkeep b/apps/angular/react-in-angular/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/angular/react-in-angular/src/favicon.ico b/apps/angular/react-in-angular/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 zcmeI332;U^%p|z7g|#(P)qFEA@4f!_@qOK2 z_lJl}!lhL!VT_U|uN7%8B2iKH??xhDa;*`g{yjTFWHvXn;2s{4R7kH|pKGdy(7z!K zgftM+Ku7~24TLlh(!g)gz|foI94G^t2^IO$uvX$3(OR0<_5L2sB)lMAMy|+`xodJ{ z_Uh_1m)~h?a;2W{dmhM;u!YGo=)OdmId_B<%^V^{ovI@y`7^g1_V9G}*f# zNzAtvou}I!W1#{M^@ROc(BZ! z+F!!_aR&Px3_reO(EW+TwlW~tv*2zr?iP7(d~a~yA|@*a89IUke+c472NXM0wiX{- zl`UrZC^1XYyf%1u)-Y)jj9;MZ!SLfd2Hl?o|80Su%Z?To_=^g_Jt0oa#CT*tjx>BI z16wec&AOWNK<#i0Qd=1O$fymLRoUR*%;h@*@v7}wApDl^w*h}!sYq%kw+DKDY)@&A z@9$ULEB3qkR#85`lb8#WZw=@})#kQig9oqy^I$dj&k4jU&^2(M3q{n1AKeGUKPFbr z1^<)aH;VsG@J|B&l>UtU#Ejv3GIqERzYgL@UOAWtW<{p#zy`WyJgpCy8$c_e%wYJL zyGHRRx38)HyjU3y{-4z6)pzb>&Q1pR)B&u01F-|&Gx4EZWK$nkUkOI|(D4UHOXg_- zw{OBf!oWQUn)Pe(=f=nt=zkmdjpO^o8ZZ9o_|4tW1ni+Un9iCW47*-ut$KQOww!;u z`0q)$s6IZO!~9$e_P9X!hqLxu`fpcL|2f^I5d4*a@Dq28;@2271v_N+5HqYZ>x;&O z05*7JT)mUe&%S0@UD)@&8SmQrMtsDfZT;fkdA!r(S=}Oz>iP)w=W508=Rc#nNn7ym z1;42c|8($ALY8#a({%1#IXbWn9-Y|0eDY$_L&j{63?{?AH{);EzcqfydD$@-B`Y3<%IIj7S7rK_N}je^=dEk%JQ4c z!tBdTPE3Tse;oYF>cnrapWq*o)m47X1`~6@(!Y29#>-#8zm&LXrXa(3=7Z)ElaQqj z-#0JJy3Fi(C#Rx(`=VXtJ63E2_bZGCz+QRa{W0e2(m3sI?LOcUBx)~^YCqZ{XEPX)C>G>U4tfqeH8L(3|pQR*zbL1 zT9e~4Tb5p9_G}$y4t`i*4t_Mr9QYvL9C&Ah*}t`q*}S+VYh0M6GxTTSXI)hMpMpIq zD1ImYqJLzbj0}~EpE-aH#VCH_udYEW#`P2zYmi&xSPs_{n6tBj=MY|-XrA;SGA_>y zGtU$?HXm$gYj*!N)_nQ59%lQdXtQZS3*#PC-{iB_sm+ytD*7j`D*k(P&IH2GHT}Eh z5697eQECVIGQAUe#eU2I!yI&%0CP#>%6MWV z@zS!p@+Y1i1b^QuuEF*13CuB zu69dve5k7&Wgb+^s|UB08Dr3u`h@yM0NTj4h7MnHo-4@xmyr7(*4$rpPwsCDZ@2be zRz9V^GnV;;?^Lk%ynzq&K(Aix`mWmW`^152Hoy$CTYVehpD-S1-W^#k#{0^L`V6CN+E z!w+xte;2vu4AmVNEFUOBmrBL>6MK@!O2*N|2=d|Y;oN&A&qv=qKn73lDD zI(+oJAdgv>Yr}8(&@ZuAZE%XUXmX(U!N+Z_sjL<1vjy1R+1IeHt`79fnYdOL{$ci7 z%3f0A*;Zt@ED&Gjm|OFTYBDe%bbo*xXAQsFz+Q`fVBH!N2)kaxN8P$c>sp~QXnv>b zwq=W3&Mtmih7xkR$YA)1Yi?avHNR6C99!u6fh=cL|KQ&PwF!n@ud^n(HNIImHD!h87!i*t?G|p0o+eelJ?B@A64_9%SBhNaJ64EvKgD&%LjLCYnNfc; znj?%*p@*?dq#NqcQFmmX($wms@CSAr9#>hUR^=I+=0B)vvGX%T&#h$kmX*s=^M2E!@N9#m?LhMvz}YB+kd zG~mbP|D(;{s_#;hsKK9lbVK&Lo734x7SIFJ9V_}2$@q?zm^7?*XH94w5Qae{7zOMUF z^?%F%)c1Y)Q?Iy?I>knw*8gYW#ok|2gdS=YYZLiD=CW|Nj;n^x!=S#iJ#`~Ld79+xXpVmUK^B(xO_vO!btA9y7w3L3-0j-y4 z?M-V{%z;JI`bk7yFDcP}OcCd*{Q9S5$iGA7*E1@tfkyjAi!;wP^O71cZ^Ep)qrQ)N z#wqw0_HS;T7x3y|`P==i3hEwK%|>fZ)c&@kgKO1~5<5xBSk?iZV?KI6&i72H6S9A* z=U(*e)EqEs?Oc04)V-~K5AUmh|62H4*`UAtItO$O(q5?6jj+K^oD!04r=6#dsxp?~}{`?&sXn#q2 zGuY~7>O2=!u@@Kfu7q=W*4egu@qPMRM>(eyYyaIE<|j%d=iWNdGsx%c!902v#ngNg z@#U-O_4xN$s_9?(`{>{>7~-6FgWpBpqXb`Ydc3OFL#&I}Irse9F_8R@4zSS*Y*o*B zXL?6*Aw!AfkNCgcr#*yj&p3ZDe2y>v$>FUdKIy_2N~}6AbHc7gA3`6$g@1o|dE>vz z4pl(j9;kyMsjaw}lO?(?Xg%4k!5%^t#@5n=WVc&JRa+XT$~#@rldvN3S1rEpU$;XgxVny7mki3 z-Hh|jUCHrUXuLr!)`w>wgO0N%KTB-1di>cj(x3Bav`7v z3G7EIbU$z>`Nad7Rk_&OT-W{;qg)-GXV-aJT#(ozdmnA~Rq3GQ_3mby(>q6Ocb-RgTUhTN)))x>m&eD;$J5Bg zo&DhY36Yg=J=$Z>t}RJ>o|@hAcwWzN#r(WJ52^g$lh^!63@hh+dR$&_dEGu&^CR*< z!oFqSqO@>xZ*nC2oiOd0eS*F^IL~W-rsrO`J`ej{=ou_q^_(<$&-3f^J z&L^MSYWIe{&pYq&9eGaArA~*kA + + + + angular-react-in-angular + + + + + + + + diff --git a/apps/angular/react-in-angular/src/main.ts b/apps/angular/react-in-angular/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/react-in-angular/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/react-in-angular/src/styles.scss b/apps/angular/react-in-angular/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/angular/react-in-angular/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/angular/react-in-angular/src/test-setup.ts b/apps/angular/react-in-angular/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/angular/react-in-angular/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/angular/react-in-angular/tailwind.config.js b/apps/angular/react-in-angular/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/angular/react-in-angular/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/angular/react-in-angular/tsconfig.app.json b/apps/angular/react-in-angular/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/angular/react-in-angular/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/angular/react-in-angular/tsconfig.editor.json b/apps/angular/react-in-angular/tsconfig.editor.json new file mode 100644 index 000000000..8ae117d96 --- /dev/null +++ b/apps/angular/react-in-angular/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/angular/react-in-angular/tsconfig.json b/apps/angular/react-in-angular/tsconfig.json new file mode 100644 index 000000000..7a9f4b7a7 --- /dev/null +++ b/apps/angular/react-in-angular/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "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/angular/react-in-angular/tsconfig.spec.json b/apps/angular/react-in-angular/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/angular/react-in-angular/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 a48a4f1cb..69704658e 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,6 +1,6 @@ { - "total": 44, + "total": 45, "🟢": 16, "🟠": 120, - "🔴": 208 + "🔴": 209 } diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md new file mode 100644 index 000000000..6aae8fbbc --- /dev/null +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -0,0 +1,76 @@ +--- +title: 🔴 React in angular +description: Challenge 45 is about learning how to benefit from the numerous libraries in React +author: Wandrille Guesdon +challengeNumber: 45 +command: angular-react-in-angular +sidebar: + order: NaN + badge: New +--- + +The goal of this challenge is to use a React component inside an Angular application. + +Many components are available in React, and it can be interesting to use them in an Angular application. The goal is to create a React component and use it in an Angular application. + +## Information + +In this challenge, we have a simple application and a react component `ReactPost` in `app/react` to illustrate a react component from a library. + +## Statement + +- Your task is to display the posts with the React component `ReactPost`. +- When you select a post, the post should be highlighted. + +In order to play with the react component, you should start by installing the react dependencies. + +```bash +npm i --save react react-dom +npm i --save-dev @types/react @types/react-dom +``` + +## Constraints + +- Do not transform the react component in an angular component. The React component is pretty simple and can be written with ease in Angular. But **the goal is to use the React component**. + +### Hint + +
+ Hint 1 - Configuration + Allow the React files in tsconfig.json + +``` +{ +... +"compilerOptions": { + ... + "jsx": "react" +}, +... +} +``` + +
+ +
+ Hint 2 - Initialization + Create a react root with `createRoot(...)` +
+ +
+ Hint 3 - Display + To render the component, it should look like this: + + ``` + .render( + + ... + + ) + ``` +
+ +
+ Hint 4 - Design + Do not forget to allow the react file in Tailwind. +
diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index e164844f8..ce07092da 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -23,16 +23,16 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositorio contiene 44 desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. + + Este repositorio contiene 45 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades. - + @@ -57,7 +57,8 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro' - Completar estos desafíos te preparará para cualquier desafío técnico que puedas encontrar en un rol de frontend durante las entrevistas. + Completar estos desafíos te preparará para cualquier desafío técnico que + puedas encontrar en un rol de frontend durante las entrevistas. diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index 892cda6c4..2388d8dff 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -25,15 +25,15 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Ce répertoire rassemble 44 défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. + + Ce répertoire rassemble 45 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. - + diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 968084a93..7185c30a3 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -24,17 +24,16 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../components/MyIcon.astro'; -import SubscriptionForm from '../../components/SubscriptionForm.astro' - +import SubscriptionForm from '../../components/SubscriptionForm.astro'; - - This repository gathers 44 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. + + This repository gathers 45 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. These challenges resolve around real-life issues or specific features to elevate your skills. - + diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx index 3004dae3c..a2bd9bb18 100644 --- a/docs/src/content/docs/pt/index.mdx +++ b/docs/src/content/docs/pt/index.mdx @@ -23,19 +23,20 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositório possui 44 desafios relacionados a Angular, Nx, RxJS, + + Este repositório possui 45 Desafios relacionados a Angular, Nx, RxJS, Ngrx e Typescript. Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de melhorar suas habilidades. - - - +{' '} + + + {' '} diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx index ac0cb90b9..349ac708c 100644 --- a/docs/src/content/docs/ru/index.mdx +++ b/docs/src/content/docs/ru/index.mdx @@ -23,36 +23,38 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Этот репозиторий содержит 44 испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. + + Этот репозиторий содержит 45 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас. - + - Одна из целей этого репозитория снизить барьер для разработки - открытого программного обеспечения (OSS). Решив эти задачи, вы поймете, - как начать вносить свой вклад в любой другой проект с открытым исходным кодом. + Одна из целей этого репозитория снизить барьер для разработки открытого + программного обеспечения (OSS). Решив эти задачи, вы поймете, как начать + вносить свой вклад в любой другой проект с открытым исходным кодом. - Изучение и использование нового фреймворка всегда сопряжено с трудностями. - В этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на практике то, чему вы научились. - Любой может оставить комментарий или предложить помощь. + Изучение и использование нового фреймворка всегда сопряжено с трудностями. В + этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на + практике то, чему вы научились. Любой может оставить комментарий или + предложить помощь. - Учиться одному - здорово, но обучение вместе с другими поможет вам добиться большего. + Учиться одному - здорово, но обучение вместе с другими поможет вам добиться + большего. У вас есть идея или интересный баг? Не стесняйтесь;{' '} - Создавайте свои собственные испытания не теряя времени. + Создавайте свои собственные испытания не теряя времени. @@ -61,8 +63,9 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro' - Это бесплатный проект, и он будет оставаться таковым как можно дольше. - Однако вся работа ведется в мое свободное время, включая создание новых испытаний и ревью их решений(PRs). + Это бесплатный проект, и он будет оставаться таковым как можно дольше. Однако + вся работа ведется в мое свободное время, включая создание новых испытаний и + ревью их решений(PRs). Спонсорство может поддержать меня и способствовать развитию проекта. From 7458977d354145ad34f03ce8e987313b2d105ff0 Mon Sep 17 00:00:00 2001 From: Wandrille Date: Fri, 9 Feb 2024 09:25:05 +0100 Subject: [PATCH 002/361] feat: add answer for challenge 45 add one possible answer for the new challenge 45. --- .../src/app/react/ReactPost.tsx | 2 +- .../src/app/react/post.component.tsx | 48 +++++++++++ .../react-in-angular/tailwind.config.js | 2 +- apps/angular/react-in-angular/tsconfig.json | 1 + package-lock.json | 84 +++++++++++++++++++ package.json | 4 + 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 apps/angular/react-in-angular/src/app/react/post.component.tsx diff --git a/apps/angular/react-in-angular/src/app/react/ReactPost.tsx b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx index 6ff7b4df4..a49d9324a 100644 --- a/apps/angular/react-in-angular/src/app/react/ReactPost.tsx +++ b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx @@ -1,4 +1,4 @@ -// import React from 'react'; +import React from 'react'; export default function ReactPost(props: { title?: string, diff --git a/apps/angular/react-in-angular/src/app/react/post.component.tsx b/apps/angular/react-in-angular/src/app/react/post.component.tsx new file mode 100644 index 000000000..882e21b20 --- /dev/null +++ b/apps/angular/react-in-angular/src/app/react/post.component.tsx @@ -0,0 +1,48 @@ +import { AfterViewInit, Component, ElementRef, EventEmitter, input, OnChanges, Output, ViewChild } from '@angular/core'; +import { createRoot, Root } from 'react-dom/client'; +import React from 'react'; +import ReactPost from './ReactPost'; + +type Post = { title: string; description: string, pictureLink: string }; + + +@Component({ + standalone: true, + selector: 'app-post', + template: ` +
`, + styles: [''] +}) +export class PostComponent implements AfterViewInit, OnChanges { + @ViewChild('react', { static: true }) containerRef!: ElementRef; + + post = input(undefined); + isSelected = input(false); + @Output() selectPost = new EventEmitter(); + root?: Root; + + ngOnChanges(): void { + this.render(); + } + + ngAfterViewInit() { + this.root = createRoot(this.containerRef.nativeElement); + this.render(); + } + + private render() { + if (this.root) { + this.root.render( + + this.selectPost.emit()} + selected={this.isSelected()} + /> + + ); + } + } +} diff --git a/apps/angular/react-in-angular/tailwind.config.js b/apps/angular/react-in-angular/tailwind.config.js index 38183db2c..99b4c147d 100644 --- a/apps/angular/react-in-angular/tailwind.config.js +++ b/apps/angular/react-in-angular/tailwind.config.js @@ -4,7 +4,7 @@ const { join } = require('path'); /** @type {import('tailwindcss').Config} */ module.exports = { content: [ - join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html,tsx}'), ...createGlobPatternsForDependencies(__dirname), ], theme: { diff --git a/apps/angular/react-in-angular/tsconfig.json b/apps/angular/react-in-angular/tsconfig.json index 7a9f4b7a7..3c5ef57f4 100644 --- a/apps/angular/react-in-angular/tsconfig.json +++ b/apps/angular/react-in-angular/tsconfig.json @@ -9,6 +9,7 @@ "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, + "jsx": "react", }, "files": [], "include": [], diff --git a/package-lock.json b/package-lock.json index 795271824..b292ca44e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,8 @@ "@rx-angular/template": "^17.0.0", "@swc/helpers": "0.5.3", "@tanstack/angular-query-experimental": "^5.12.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", "rxjs": "7.8.1", "tailwindcss": "^3.3.5", "tslib": "^2.3.0", @@ -71,6 +73,8 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "29.4.0", "@types/node": "18.16.9", + "@types/react": "^18.2.55", + "@types/react-dom": "^18.2.19", "@typescript-eslint/eslint-plugin": "6.11.0", "@typescript-eslint/parser": "6.11.0", "all-contributors-cli": "^6.26.1", @@ -8837,6 +8841,12 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "dev": true + }, "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", @@ -8847,6 +8857,26 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, + "node_modules/@types/react": { + "version": "18.2.55", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz", + "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", + "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -8867,6 +8897,12 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -12674,6 +12710,12 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "devOptional": true }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, "node_modules/cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -20348,6 +20390,17 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -24012,6 +24065,29 @@ "node": ">= 0.8" } }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -24972,6 +25048,14 @@ "node": ">=v12.22.7" } }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", diff --git a/package.json b/package.json index 3507f1bb6..a4aa3dd2f 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ "@rx-angular/template": "^17.0.0", "@swc/helpers": "0.5.3", "@tanstack/angular-query-experimental": "^5.12.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", "rxjs": "7.8.1", "tailwindcss": "^3.3.5", "tslib": "^2.3.0", @@ -74,6 +76,8 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "29.4.0", "@types/node": "18.16.9", + "@types/react": "^18.2.55", + "@types/react-dom": "^18.2.19", "@typescript-eslint/eslint-plugin": "6.11.0", "@typescript-eslint/parser": "6.11.0", "all-contributors-cli": "^6.26.1", From ebf6b135f88c36ec075ee93941eed194e99312bf Mon Sep 17 00:00:00 2001 From: Wandrille Date: Thu, 15 Feb 2024 07:54:55 +0100 Subject: [PATCH 003/361] Revert "feat: add answer for challenge 45" This reverts commit 7458977d354145ad34f03ce8e987313b2d105ff0. --- .../src/app/react/ReactPost.tsx | 2 +- .../src/app/react/post.component.tsx | 48 ----------- .../react-in-angular/tailwind.config.js | 2 +- apps/angular/react-in-angular/tsconfig.json | 1 - package-lock.json | 84 ------------------- package.json | 4 - 6 files changed, 2 insertions(+), 139 deletions(-) delete mode 100644 apps/angular/react-in-angular/src/app/react/post.component.tsx diff --git a/apps/angular/react-in-angular/src/app/react/ReactPost.tsx b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx index a49d9324a..6ff7b4df4 100644 --- a/apps/angular/react-in-angular/src/app/react/ReactPost.tsx +++ b/apps/angular/react-in-angular/src/app/react/ReactPost.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +// import React from 'react'; export default function ReactPost(props: { title?: string, diff --git a/apps/angular/react-in-angular/src/app/react/post.component.tsx b/apps/angular/react-in-angular/src/app/react/post.component.tsx deleted file mode 100644 index 882e21b20..000000000 --- a/apps/angular/react-in-angular/src/app/react/post.component.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, input, OnChanges, Output, ViewChild } from '@angular/core'; -import { createRoot, Root } from 'react-dom/client'; -import React from 'react'; -import ReactPost from './ReactPost'; - -type Post = { title: string; description: string, pictureLink: string }; - - -@Component({ - standalone: true, - selector: 'app-post', - template: ` -
`, - styles: [''] -}) -export class PostComponent implements AfterViewInit, OnChanges { - @ViewChild('react', { static: true }) containerRef!: ElementRef; - - post = input(undefined); - isSelected = input(false); - @Output() selectPost = new EventEmitter(); - root?: Root; - - ngOnChanges(): void { - this.render(); - } - - ngAfterViewInit() { - this.root = createRoot(this.containerRef.nativeElement); - this.render(); - } - - private render() { - if (this.root) { - this.root.render( - - this.selectPost.emit()} - selected={this.isSelected()} - /> - - ); - } - } -} diff --git a/apps/angular/react-in-angular/tailwind.config.js b/apps/angular/react-in-angular/tailwind.config.js index 99b4c147d..38183db2c 100644 --- a/apps/angular/react-in-angular/tailwind.config.js +++ b/apps/angular/react-in-angular/tailwind.config.js @@ -4,7 +4,7 @@ const { join } = require('path'); /** @type {import('tailwindcss').Config} */ module.exports = { content: [ - join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html,tsx}'), + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), ...createGlobPatternsForDependencies(__dirname), ], theme: { diff --git a/apps/angular/react-in-angular/tsconfig.json b/apps/angular/react-in-angular/tsconfig.json index 3c5ef57f4..7a9f4b7a7 100644 --- a/apps/angular/react-in-angular/tsconfig.json +++ b/apps/angular/react-in-angular/tsconfig.json @@ -9,7 +9,6 @@ "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "jsx": "react", }, "files": [], "include": [], diff --git a/package-lock.json b/package-lock.json index b292ca44e..795271824 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,8 +32,6 @@ "@rx-angular/template": "^17.0.0", "@swc/helpers": "0.5.3", "@tanstack/angular-query-experimental": "^5.12.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", "rxjs": "7.8.1", "tailwindcss": "^3.3.5", "tslib": "^2.3.0", @@ -73,8 +71,6 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "29.4.0", "@types/node": "18.16.9", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", "@typescript-eslint/eslint-plugin": "6.11.0", "@typescript-eslint/parser": "6.11.0", "all-contributors-cli": "^6.26.1", @@ -8841,12 +8837,6 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", @@ -8857,26 +8847,6 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, - "node_modules/@types/react": { - "version": "18.2.55", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz", - "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.2.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", - "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -8897,12 +8867,6 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true - }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -12710,12 +12674,6 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "devOptional": true }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, "node_modules/cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -20390,17 +20348,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -24065,29 +24012,6 @@ "node": ">= 0.8" } }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -25048,14 +24972,6 @@ "node": ">=v12.22.7" } }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", diff --git a/package.json b/package.json index a4aa3dd2f..3507f1bb6 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,6 @@ "@rx-angular/template": "^17.0.0", "@swc/helpers": "0.5.3", "@tanstack/angular-query-experimental": "^5.12.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", "rxjs": "7.8.1", "tailwindcss": "^3.3.5", "tslib": "^2.3.0", @@ -76,8 +74,6 @@ "@testing-library/user-event": "^14.5.1", "@types/jest": "29.4.0", "@types/node": "18.16.9", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", "@typescript-eslint/eslint-plugin": "6.11.0", "@typescript-eslint/parser": "6.11.0", "all-contributors-cli": "^6.26.1", From 0e7851f6e1bbb54f9575da081d9af062f90fab78 Mon Sep 17 00:00:00 2001 From: Wandrille Date: Thu, 15 Feb 2024 07:56:52 +0100 Subject: [PATCH 004/361] fix: add author file --- docs/src/content/authors/wandrille-guesdon.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/src/content/authors/wandrille-guesdon.json diff --git a/docs/src/content/authors/wandrille-guesdon.json b/docs/src/content/authors/wandrille-guesdon.json new file mode 100644 index 000000000..a240cba89 --- /dev/null +++ b/docs/src/content/authors/wandrille-guesdon.json @@ -0,0 +1,5 @@ +{ + "name": "Wandrille Guesdon", + "linkedin": "https://www.linkedin.com/in/wandrille-guesdon-53a54684/", + "github": "https://github.com/wandri" +} From cf588ff92572ffa5a70057f277f84f2ea5813c85 Mon Sep 17 00:00:00 2001 From: Wandrille Date: Thu, 15 Feb 2024 16:54:36 +0100 Subject: [PATCH 005/361] fix: the author field matches the name of the file --- docs/src/content/docs/challenges/angular/45-react-in-angular.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md index 6aae8fbbc..e71ab6834 100644 --- a/docs/src/content/docs/challenges/angular/45-react-in-angular.md +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -1,7 +1,7 @@ --- title: 🔴 React in angular description: Challenge 45 is about learning how to benefit from the numerous libraries in React -author: Wandrille Guesdon +author: wandrille-guesdon challengeNumber: 45 command: angular-react-in-angular sidebar: From 8cdaef0b3829c98c718389e49a1e5e6a9fff6486 Mon Sep 17 00:00:00 2001 From: thomas Date: Thu, 15 Feb 2024 17:37:29 +0100 Subject: [PATCH 006/361] fix: frontmatter --- .../content/docs/challenges/angular/44-view-transition.md | 1 - .../content/docs/challenges/angular/45-react-in-angular.md | 7 ++++--- .../docs/pt/challenges/angular/44-view-transition.md | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/44-view-transition.md b/docs/src/content/docs/challenges/angular/44-view-transition.md index 46ae58010..6dbf21131 100644 --- a/docs/src/content/docs/challenges/angular/44-view-transition.md +++ b/docs/src/content/docs/challenges/angular/44-view-transition.md @@ -6,7 +6,6 @@ challengeNumber: 44 command: angular-view-transition sidebar: order: 208 - badge: New --- ## Information diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md index e71ab6834..96443c7f3 100644 --- a/docs/src/content/docs/challenges/angular/45-react-in-angular.md +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -5,7 +5,7 @@ author: wandrille-guesdon challengeNumber: 45 command: angular-react-in-angular sidebar: - order: NaN + order: 209 badge: New --- @@ -60,14 +60,15 @@ npm i --save-dev @types/react @types/react-dom
Hint 3 - Display To render the component, it should look like this: - + ``` .render( ... ) - ``` + ``` +
diff --git a/docs/src/content/docs/pt/challenges/angular/44-view-transition.md b/docs/src/content/docs/pt/challenges/angular/44-view-transition.md index 7391bb414..ead29d495 100644 --- a/docs/src/content/docs/pt/challenges/angular/44-view-transition.md +++ b/docs/src/content/docs/pt/challenges/angular/44-view-transition.md @@ -6,7 +6,6 @@ challengeNumber: 44 command: angular-view-transition sidebar: order: 208 - badge: New --- ## Informação From 115ec09d391e609e9e7ccfb4edb7986b94a5584d Mon Sep 17 00:00:00 2001 From: thomas Date: Thu, 15 Feb 2024 17:47:21 +0100 Subject: [PATCH 007/361] fix: homepage link --- docs/src/content/docs/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 7185c30a3..b9a57157f 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Go to the latest Challenge - link: /challenges/angular/44-view-transition/ + link: /challenges/angular/45-react-in-angular/ icon: rocket - text: Give a star link: https://github.com/tomalaforge/angular-challenges From 25d6b513b4aa6bbc7996e5b83cd8466fd0e668ff Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 17:08:23 +0000 Subject: [PATCH 008/361] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de881440c..3fc04fb21 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Check [all 45 challenges](https://angular-challenges.vercel.app/) Erick Rodriguez
Erick Rodriguez

🇪🇸 Eduardo Roth
Eduardo Roth

📖 🇪🇸 Fernando Bello
Fernando Bello

📖 + Wandrille
Wandrille

💻 From c68b8f30e9e25ca4dbb081f85db3ca3bcaa92aeb Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 17:08:24 +0000 Subject: [PATCH 009/361] docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 38856b436..5c281a249 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -201,6 +201,15 @@ "contributions": [ "doc" ] + }, + { + "login": "wandri", + "name": "Wandrille", + "avatar_url": "https://avatars.githubusercontent.com/u/15016833?v=4", + "profile": "https://wandrille-guesdon.com/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, From b3f863a60d7016219d16c077cb9b21b1be86753b Mon Sep 17 00:00:00 2001 From: thomas Date: Thu, 15 Feb 2024 18:11:19 +0100 Subject: [PATCH 010/361] feat: update contribution --- .all-contributorsrc | 20 ++++++++++---------- README.md | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5c281a249..062fd18c8 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -79,6 +79,15 @@ "translation-ru" ] }, + { + "login": "wandri", + "name": "Wandrille", + "avatar_url": "https://avatars.githubusercontent.com/u/15016833?v=4", + "profile": "https://wandrille-guesdon.com/", + "contributions": [ + "challenge" + ] + }, { "login": "alan-bio", "name": "Alan Dragicevich", @@ -201,18 +210,9 @@ "contributions": [ "doc" ] - }, - { - "login": "wandri", - "name": "Wandrille", - "avatar_url": "https://avatars.githubusercontent.com/u/15016833?v=4", - "profile": "https://wandrille-guesdon.com/", - "contributions": [ - "code" - ] } ], "contributorsPerLine": 7, "linkToUsage": true, "commitType": "docs" -} +} \ No newline at end of file diff --git a/README.md b/README.md index 3fc04fb21..d8662ab35 100644 --- a/README.md +++ b/README.md @@ -38,24 +38,24 @@ Check [all 45 challenges](https://angular-challenges.vercel.app/) J. Degand
J. Degand

📖 🖋 💻 Devesh Chaudhari
Devesh Chaudhari

💻 🐛 🧩 stillst
stillst

🧩 🇷🇺 + Wandrille
Wandrille

🧩 Alan Dragicevich
Alan Dragicevich

📖 Michel EDIGHOFFER
Michel EDIGHOFFER

📖 - Gerardo Sebastian Gonzalez
Gerardo Sebastian Gonzalez

📖 + Gerardo Sebastian Gonzalez
Gerardo Sebastian Gonzalez

📖 Evseev Yuriy
Evseev Yuriy

🐛 Tomer953
Tomer953

🐛 📖 💻 Dmitriy Mishchenko
Dmitriy Mishchenko

📖 Sagar Devkota
Sagar Devkota

📖 💻 Nelson Gutierrez
Nelson Gutierrez

🇪🇸 Hossain K. M.
Hossain K. M.

📖 - Diogo Nishikawa
Diogo Nishikawa

💻 🇵🇹 📖 + Diogo Nishikawa
Diogo Nishikawa

💻 🇵🇹 📖 Erick Rodriguez
Erick Rodriguez

🇪🇸 Eduardo Roth
Eduardo Roth

📖 🇪🇸 Fernando Bello
Fernando Bello

📖 - Wandrille
Wandrille

💻 From f27cc5e1eac2a1ffa955afbc0bd607805e72eb6c Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Thu, 15 Feb 2024 21:51:43 +0100 Subject: [PATCH 011/361] docs: fix exercice typo in docs french to english --- docs/src/content/docs/challenges/angular/10-pipe-utility.md | 2 +- docs/src/content/docs/challenges/angular/22-router-input.md | 2 +- .../docs/challenges/angular/3-directive-enhancement.md | 4 ++-- .../content/docs/challenges/angular/4-context-outlet-typed.md | 4 ++-- docs/src/content/docs/challenges/angular/5-crud.md | 2 +- docs/src/content/docs/challenges/angular/8-pipe-pure.md | 2 +- docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md | 2 +- docs/src/content/docs/challenges/ngrx/2-effect-selector.md | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/challenges/angular/10-pipe-utility.md index f8688ddfb..bab388666 100644 --- a/docs/src/content/docs/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/challenges/angular/10-pipe-utility.md @@ -14,7 +14,7 @@ Pure pipes are a very useful way to transform data from your template. The diffe ## Information: -In this third exercice, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file where you will need to pass the name of the function you want to call and the needed arguments. +In this third exercise, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file where you will need to pass the name of the function you want to call and the needed arguments. ## Constraints: diff --git a/docs/src/content/docs/challenges/angular/22-router-input.md b/docs/src/content/docs/challenges/angular/22-router-input.md index 75ac297fd..59676ceda 100644 --- a/docs/src/content/docs/challenges/angular/22-router-input.md +++ b/docs/src/content/docs/challenges/angular/22-router-input.md @@ -23,4 +23,4 @@ In version 16, Angular introduced a new `Input` that can listen to route data. Y ## Statement -The goal of this exercice is to refactor the code to use the new `RouterInput` strategy. +The goal of this exercise is to refactor the code to use the new `RouterInput` strategy. diff --git a/docs/src/content/docs/challenges/angular/3-directive-enhancement.md b/docs/src/content/docs/challenges/angular/3-directive-enhancement.md index 41a0cadb9..3c8182cdc 100644 --- a/docs/src/content/docs/challenges/angular/3-directive-enhancement.md +++ b/docs/src/content/docs/challenges/angular/3-directive-enhancement.md @@ -10,7 +10,7 @@ sidebar: --- :::note -This exercice can feel obsolete with the new control flow and the empty block inside the `@for` block. However **structural directives** are not going to be deleted any time soon, so you can still learn a lot from this exercice. +This exercise can feel obsolete with the new control flow and the empty block inside the `@for` block. However **structural directives** are not going to be deleted any time soon, so you can still learn a lot from this exercise. ::: ## Information @@ -21,7 +21,7 @@ But the real power is that you can enhance an already existing directive which m ## Statement -In this exercice, we have a want to display a list of persons. If the list is empty, you must display _" the list is empty !! "_. +In this exercise, we have a want to display a list of persons. If the list is empty, you must display _" the list is empty !! "_. Currently we have : diff --git a/docs/src/content/docs/challenges/angular/4-context-outlet-typed.md b/docs/src/content/docs/challenges/angular/4-context-outlet-typed.md index 43f8a2d95..88d4e5bfc 100644 --- a/docs/src/content/docs/challenges/angular/4-context-outlet-typed.md +++ b/docs/src/content/docs/challenges/angular/4-context-outlet-typed.md @@ -17,9 +17,9 @@ However the context of **NgTemplateOutlet** type is **Object**. But with the hel ## Statement -In this exercice, we want to learn how to strongly type our ng-template in our AppComponent. +In this exercise, we want to learn how to strongly type our ng-template in our AppComponent. -This exercice has two levels of complexity. +This exercise has two levels of complexity. ### Level 1: known Interface diff --git a/docs/src/content/docs/challenges/angular/5-crud.md b/docs/src/content/docs/challenges/angular/5-crud.md index dfc909fbc..9d34d5a59 100644 --- a/docs/src/content/docs/challenges/angular/5-crud.md +++ b/docs/src/content/docs/challenges/angular/5-crud.md @@ -14,7 +14,7 @@ Communicating and having a global/local state in sync with your backend is the h ## Statement -In this exercice, you have a small CRUD application, which get a list of TODOS, update and delete some todos. +In this exercise, you have a small CRUD application, which get a list of TODOS, update and delete some todos. Currently we have a working example but filled with lots of bad practices. diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index 58620cba0..04fe2c6a5 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -15,7 +15,7 @@ Pure pipes are a very useful way to transform data from your template. The diffe ## Information -In this first exercice, you call a simple function inside your template. The goal is to convert it to a pipe. +In this first exercise, you call a simple function inside your template. The goal is to convert it to a pipe. ## Constraints diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index a50aa09a9..2048f35a0 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -15,7 +15,7 @@ Pure pipes are a very useful way to transform data from your template. The diffe ## Information: -In this second exercice, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. +In this second exercise, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.** ## Constraints: diff --git a/docs/src/content/docs/challenges/ngrx/2-effect-selector.md b/docs/src/content/docs/challenges/ngrx/2-effect-selector.md index f571bbf7f..ea7914bd7 100644 --- a/docs/src/content/docs/challenges/ngrx/2-effect-selector.md +++ b/docs/src/content/docs/challenges/ngrx/2-effect-selector.md @@ -9,7 +9,7 @@ sidebar: order: 113 --- -For this exercice, you will have a dashboard of activities displaying the name, the main teacher and a list of subtitutes. +For this exercise, you will have a dashboard of activities displaying the name, the main teacher and a list of subtitutes. ## Information From 1ebbf66a28e252a185406efbd72ed58c892fa2c2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:14:28 +0000 Subject: [PATCH 012/361] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d8662ab35..a35021200 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Check [all 45 challenges](https://angular-challenges.vercel.app/) Erick Rodriguez
Erick Rodriguez

🇪🇸 Eduardo Roth
Eduardo Roth

📖 🇪🇸 Fernando Bello
Fernando Bello

📖 + Sven Brodny
Sven Brodny

📖 From 6c40408b3e1c5543f901b235e43d7c79313339e6 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:14:29 +0000 Subject: [PATCH 013/361] docs: update .all-contributorsrc --- .all-contributorsrc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 062fd18c8..5e94f8a01 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -210,9 +210,18 @@ "contributions": [ "doc" ] + }, + { + "login": "svenson95", + "name": "Sven Brodny", + "avatar_url": "https://avatars.githubusercontent.com/u/46655156?v=4", + "profile": "https://svenson95.github.io/sb-portfolio/", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, "linkToUsage": true, "commitType": "docs" -} \ No newline at end of file +} From 2f41cc8e615280ee19c2615ba80489da842a02a5 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Thu, 15 Feb 2024 23:24:05 +0100 Subject: [PATCH 014/361] docs(projection): add related link reasons for avoiding magic strings --- docs/src/content/docs/challenges/angular/1-projection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/1-projection.md b/docs/src/content/docs/challenges/angular/1-projection.md index 160251000..f3409b119 100644 --- a/docs/src/content/docs/challenges/angular/1-projection.md +++ b/docs/src/content/docs/challenges/angular/1-projection.md @@ -40,4 +40,4 @@ While the application works, the developer experience is far from being optimal. - Try to work with the new built-in control flow syntax for loops and conditionals (documentation [here](https://angular.dev/guide/templates/control-flow)) - Use the signal API to manage your components state (documentation [here](https://angular.dev/guide/signals)) -- To reference the template, use a directive instead of magic strings +- To reference the template, use a directive instead of magic strings ([What is wrong with magic strings?](https://softwareengineering.stackexchange.com/a/365344)) From dcf80b54db679313a4ee6627b74dc98ba4418fb0 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 09:06:25 +0100 Subject: [PATCH 015/361] docs(pipes): update pipe challenge texts --- .../challenges/angular/10-pipe-utility.md | 19 +++++++++++++++---- .../docs/challenges/angular/8-pipe-pure.md | 19 +++++++++++++++---- .../docs/challenges/angular/9-pipe-wrapFn.md | 19 +++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/challenges/angular/10-pipe-utility.md index f8688ddfb..6e137337f 100644 --- a/docs/src/content/docs/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/challenges/angular/10-pipe-utility.md @@ -8,14 +8,25 @@ sidebar: order: 202 --- -The goal of this series of 3 pipe challenges is to master **pipe** in Angular. +This is the third of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. -Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. +Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. + +Pipes are designed to be efficient and optimized for performance. They use change detection mechanisms to only recalculate the value if the input changes, to minimize unnecessary calculations and improving rendering performance. + +By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. + +:::note +A **pure** pipe is only called mwhen the value changes. +A **impure** pipe is called for every change detection cycle no matter whether the value changes. +::: + +There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). ## Information: -In this third exercice, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file where you will need to pass the name of the function you want to call and the needed arguments. +In this exercise, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file, where you will need to pass the name of the function you want to call and the needed arguments. ## Constraints: -- must be strongly typed +- Must be strongly typed diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index 58620cba0..6e5b11a36 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -9,14 +9,25 @@ sidebar: order: 3 --- -The goal of this series of 3 pipe challenges is to master **pipe** in Angular. +This is the first of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. -Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. +Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. + +Pipes are designed to be efficient and optimized for performance. They use change detection mechanisms to only recalculate the value if the input changes, to minimize unnecessary calculations and improving rendering performance. + +By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. + +:::note +A **pure** pipe is only called mwhen the value changes. +A **impure** pipe is called for every change detection cycle no matter whether the value changes. +::: + +There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). ## Information -In this first exercice, you call a simple function inside your template. The goal is to convert it to a pipe. +In this exercise, you need to refactor a transform function inside a component, which is called inside your template. The goal is to convert this function to a pipe. ## Constraints -- must be strongly typed +- Must be strongly typed diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index a50aa09a9..9c97bcdc1 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -9,15 +9,26 @@ sidebar: order: 103 --- -The goal of this series of 3 pipe challenges is to master **pipe** in Angular. +This is the second of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. -Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. +Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. + +Pipes are designed to be efficient and optimized for performance. They use change detection mechanisms to only recalculate the value if the input changes, to minimize unnecessary calculations and improving rendering performance. + +By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. + +:::note +A **pure** pipe is only called mwhen the value changes. +A **impure** pipe is called for every change detection cycle no matter whether the value changes. +::: + +There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). ## Information: -In this second exercice, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. +In this exercise, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.** ## Constraints: -- must be strongly typed +- Must be strongly typed From 2f18c6dcde864e41e07c04c5242a0b47a45695a3 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 09:08:20 +0100 Subject: [PATCH 016/361] refactor(pipe-easy): update component & comments --- apps/angular/pipe-easy/src/app/app.component.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/angular/pipe-easy/src/app/app.component.ts b/apps/angular/pipe-easy/src/app/app.component.ts index 3c19fa169..73fef0474 100644 --- a/apps/angular/pipe-easy/src/app/app.component.ts +++ b/apps/angular/pipe-easy/src/app/app.component.ts @@ -7,15 +7,16 @@ import { Component } from '@angular/core'; selector: 'app-root', template: `
- {{ heavyComputation(person, index) }} + {{ numberedPerson(person, index) }}
`, }) export class AppComponent { - persons = ['toto', 'jack']; + // TODO: untyped array? + persons = ['toto', 'jack', 'samuel', 'steve']; - heavyComputation(name: string, index: number) { - // very heavy computation - return `${name} - ${index}`; + // TODO: very heavy computation, replace this function with a pipe + numberedPerson(name: string, index: number) { + return `${index + 1}. ${name}`; } } From bf45d4bb0f6807d0ef391559d35dfd0ce7942e6b Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 14:33:51 +0100 Subject: [PATCH 017/361] revert: pipe challenge changes --- apps/angular/pipe-easy/src/app/app.component.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/angular/pipe-easy/src/app/app.component.ts b/apps/angular/pipe-easy/src/app/app.component.ts index 73fef0474..e7bd6b500 100644 --- a/apps/angular/pipe-easy/src/app/app.component.ts +++ b/apps/angular/pipe-easy/src/app/app.component.ts @@ -7,16 +7,15 @@ import { Component } from '@angular/core'; selector: 'app-root', template: `
- {{ numberedPerson(person, index) }} + {{ heavyComputation(person, index) }}
`, }) export class AppComponent { - // TODO: untyped array? persons = ['toto', 'jack', 'samuel', 'steve']; - // TODO: very heavy computation, replace this function with a pipe - numberedPerson(name: string, index: number) { - return `${index + 1}. ${name}`; + // TODO: very heavy computation + heavyComputation(name: string, index: number) { + return `${name} - ${index}`; } } From f13cd8a9546e00f7521c795b4d001f2d78031c95 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 14:41:52 +0100 Subject: [PATCH 018/361] revert: pipe challenge changes (2) --- apps/angular/pipe-easy/src/app/app.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/angular/pipe-easy/src/app/app.component.ts b/apps/angular/pipe-easy/src/app/app.component.ts index e7bd6b500..efa51d525 100644 --- a/apps/angular/pipe-easy/src/app/app.component.ts +++ b/apps/angular/pipe-easy/src/app/app.component.ts @@ -12,9 +12,9 @@ import { Component } from '@angular/core'; `, }) export class AppComponent { - persons = ['toto', 'jack', 'samuel', 'steve']; + persons = ['toto', 'jack']; - // TODO: very heavy computation + // very heavy computation heavyComputation(name: string, index: number) { return `${name} - ${index}`; } From 4da002730be6f25b3ec725775892c963a2c58188 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 14:48:56 +0100 Subject: [PATCH 019/361] revert: pipe challenge changes (3) --- apps/angular/pipe-easy/src/app/app.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/angular/pipe-easy/src/app/app.component.ts b/apps/angular/pipe-easy/src/app/app.component.ts index efa51d525..3c19fa169 100644 --- a/apps/angular/pipe-easy/src/app/app.component.ts +++ b/apps/angular/pipe-easy/src/app/app.component.ts @@ -14,8 +14,8 @@ import { Component } from '@angular/core'; export class AppComponent { persons = ['toto', 'jack']; - // very heavy computation heavyComputation(name: string, index: number) { + // very heavy computation return `${name} - ${index}`; } } From 549c283f882ccfe283ff9bfdf98e4efcc163bdf2 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 22:15:49 +0100 Subject: [PATCH 020/361] docs(pipes): fix typo & add linebreak --- docs/src/content/docs/challenges/angular/10-pipe-utility.md | 2 +- docs/src/content/docs/challenges/angular/8-pipe-pure.md | 2 +- docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/challenges/angular/10-pipe-utility.md index 6e137337f..f356ec0f1 100644 --- a/docs/src/content/docs/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/challenges/angular/10-pipe-utility.md @@ -17,7 +17,7 @@ Pipes are designed to be efficient and optimized for performance. They use chang By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. :::note -A **pure** pipe is only called mwhen the value changes. +A **pure** pipe is only called when the value changes.\ A **impure** pipe is called for every change detection cycle no matter whether the value changes. ::: diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index 6e5b11a36..529ff1f04 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -18,7 +18,7 @@ Pipes are designed to be efficient and optimized for performance. They use chang By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. :::note -A **pure** pipe is only called mwhen the value changes. +A **pure** pipe is only called when the value changes.\ A **impure** pipe is called for every change detection cycle no matter whether the value changes. ::: diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index 9c97bcdc1..350a6d271 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -18,7 +18,7 @@ Pipes are designed to be efficient and optimized for performance. They use chang By default a pipe is pure, you should be aware that setting `pure` to false is prone to be inefficient, because it increases the amount of rerenders. :::note -A **pure** pipe is only called mwhen the value changes. +A **pure** pipe is only called when the value changes.\ A **impure** pipe is called for every change detection cycle no matter whether the value changes. ::: From 890f5cc430e0a43b14ea2dd77f7620751150baa9 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 22:23:32 +0100 Subject: [PATCH 021/361] docs(pipe-utility): change impure pipe description --- docs/src/content/docs/challenges/angular/10-pipe-utility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/challenges/angular/10-pipe-utility.md index f356ec0f1..24e469da5 100644 --- a/docs/src/content/docs/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/challenges/angular/10-pipe-utility.md @@ -18,7 +18,7 @@ By default a pipe is pure, you should be aware that setting `pure` to false is p :::note A **pure** pipe is only called when the value changes.\ -A **impure** pipe is called for every change detection cycle no matter whether the value changes. +A **impure** pipe is called every change detection cycle. ::: There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). From ee5fae726e766137c5e008495f4a5a4b7ce7a537 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 22:25:56 +0100 Subject: [PATCH 022/361] docs(pipes): change impure pipe description --- docs/src/content/docs/challenges/angular/8-pipe-pure.md | 2 +- docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index 529ff1f04..e69f833a7 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -19,7 +19,7 @@ By default a pipe is pure, you should be aware that setting `pure` to false is p :::note A **pure** pipe is only called when the value changes.\ -A **impure** pipe is called for every change detection cycle no matter whether the value changes. +A **impure** pipe is called every change detection cycle. ::: There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index 350a6d271..6f457669c 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -19,7 +19,7 @@ By default a pipe is pure, you should be aware that setting `pure` to false is p :::note A **pure** pipe is only called when the value changes.\ -A **impure** pipe is called for every change detection cycle no matter whether the value changes. +A **impure** pipe is called every change detection cycle. ::: There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). From 5886a0f0c914e03e757772fcbe1ed598d574aa7a Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 22:30:46 +0100 Subject: [PATCH 023/361] docs(pipes): add information and statement titles --- docs/src/content/docs/challenges/angular/10-pipe-utility.md | 6 ++++-- docs/src/content/docs/challenges/angular/8-pipe-pure.md | 2 +- docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/challenges/angular/10-pipe-utility.md index 24e469da5..f10d9f3d7 100644 --- a/docs/src/content/docs/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/challenges/angular/10-pipe-utility.md @@ -8,6 +8,8 @@ sidebar: order: 202 --- +## Information + This is the third of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. @@ -23,10 +25,10 @@ A **impure** pipe is called every change detection cycle. There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). -## Information: +## Statement In this exercise, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file, where you will need to pass the name of the function you want to call and the needed arguments. -## Constraints: +## Constraints - Must be strongly typed diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index e69f833a7..79b58a873 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -24,7 +24,7 @@ A **impure** pipe is called every change detection cycle. There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). -## Information +## Statement In this exercise, you need to refactor a transform function inside a component, which is called inside your template. The goal is to convert this function to a pipe. diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index 6f457669c..4d75ef188 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -9,6 +9,8 @@ sidebar: order: 103 --- +## Information + This is the second of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. @@ -24,7 +26,7 @@ A **impure** pipe is called every change detection cycle. There are some useful predefined pipes like the DatePipe, UpperCasePipe and CurrencyPipe. To learn more about pipes in Angular, check the API documentation [here](https://angular.io/guide/pipes). -## Information: +## Statement In this exercise, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.** From d8ed81be36d6a7f5c69ff65b06cf74b16fd4d1e6 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Fri, 16 Feb 2024 22:31:36 +0100 Subject: [PATCH 024/361] docs(pipes): add information and statement titles (2) --- docs/src/content/docs/challenges/angular/8-pipe-pure.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/content/docs/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/challenges/angular/8-pipe-pure.md index 79b58a873..e6871a466 100644 --- a/docs/src/content/docs/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/challenges/angular/8-pipe-pure.md @@ -9,6 +9,8 @@ sidebar: order: 3 --- +## Information + This is the first of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. Pipes are a very powerful way to transform data in your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed. From a6d7bda1e61528dc0ed2267fd28844b5a38404f4 Mon Sep 17 00:00:00 2001 From: jdegand <70610011+jdegand@users.noreply.github.com> Date: Fri, 16 Feb 2024 19:34:30 -0500 Subject: [PATCH 025/361] fix: typos in react md --- .../docs/challenges/angular/45-react-in-angular.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md index 96443c7f3..4ace12ee8 100644 --- a/docs/src/content/docs/challenges/angular/45-react-in-angular.md +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -15,23 +15,26 @@ Many components are available in React, and it can be interesting to use them in ## Information -In this challenge, we have a simple application and a react component `ReactPost` in `app/react` to illustrate a react component from a library. +In this challenge, we have a simple application and a React component `ReactPost` in `app/react` to illustrate a React component from a library. ## Statement - Your task is to display the posts with the React component `ReactPost`. - When you select a post, the post should be highlighted. -In order to play with the react component, you should start by installing the react dependencies. +In order to play with the React component, you should start by installing the React dependencies. ```bash npm i --save react react-dom +``` + +```bash npm i --save-dev @types/react @types/react-dom ``` ## Constraints -- Do not transform the react component in an angular component. The React component is pretty simple and can be written with ease in Angular. But **the goal is to use the React component**. +- Do not transform the React component into an Angular component. The React component is pretty simple and can be written with ease in Angular. But **the goal is to use the React component**. ### Hint From ec0e2af4de248d10489bbd49d6595b6d72f1bbf3 Mon Sep 17 00:00:00 2001 From: jdegand <70610011+jdegand@users.noreply.github.com> Date: Fri, 16 Feb 2024 19:43:22 -0500 Subject: [PATCH 026/361] fix: remove unnecessary comments --- .../view-transition/src/app/post/post-header.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/angular/view-transition/src/app/post/post-header.component.ts b/apps/angular/view-transition/src/app/post/post-header.component.ts index db2f42da0..8b62a6c48 100644 --- a/apps/angular/view-transition/src/app/post/post-header.component.ts +++ b/apps/angular/view-transition/src/app/post/post-header.component.ts @@ -6,7 +6,6 @@ import { Component, input } from '@angular/core'; standalone: true, imports: [NgOptimizedImage], template: ` -
Thomas Laforge {{ date() }} - `, host: { class: 'flex flex-col justify-center items-center', From 3e4d338eeb31a630882dc3dfe5a20c250d6dc7dd Mon Sep 17 00:00:00 2001 From: jdegand <70610011+jdegand@users.noreply.github.com> Date: Fri, 16 Feb 2024 19:54:33 -0500 Subject: [PATCH 027/361] revert: splitting bash command --- .../src/content/docs/challenges/angular/45-react-in-angular.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md index 4ace12ee8..3c56d88f1 100644 --- a/docs/src/content/docs/challenges/angular/45-react-in-angular.md +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -26,9 +26,6 @@ In order to play with the React component, you should start by installing the Re ```bash npm i --save react react-dom -``` - -```bash npm i --save-dev @types/react @types/react-dom ``` From 8bb6ab1414ed876aeb75a538d567e794ff589e32 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Sun, 18 Feb 2024 22:08:52 -0300 Subject: [PATCH 028/361] docs(pt): translate challenge 45 --- 45-react-in-angular.md | 76 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 45-react-in-angular.md diff --git a/45-react-in-angular.md b/45-react-in-angular.md new file mode 100644 index 000000000..896912486 --- /dev/null +++ b/45-react-in-angular.md @@ -0,0 +1,76 @@ +--- +title: 🔴 React em angular +description: Desafio 5 é sobre aprender como se beneficiar das vários bibliotecas em React +author: wandrille-guesdon +challengeNumber: 45 +command: angular-react-in-angular +sidebar: + order: 209 + badge: New +--- + +O objetivo deste desafio é usar um componente React dentro de uma aplicação Angular. + +Muitos componentes estão disponíveis em React, e pode ser interessante usar eles em uma aplicação Angular. O objetivo é criar um componente React e usar em uma aplicação Angular. + +## Informação + +Neste desafio temos uma simples aplicação e um componente React `ReactPost` em `app/react` para ilustrar um componente React de uma biblioteca. + +## Declaração + +- Sua tarefa é mostrar as postagens com o componente React `ReactPost`. +- Quando selecionar uma postagem, a postagem deve ser destacada. + +Para brincar com o componente React, você deve começar instalando as dependências do React. + +```bash +npm i --save react react-dom +npm i --save-dev @types/react @types/react-dom +``` + +## Restrições + +- Não transforme o componente React em um componente Angular. O componente React é bem simples e pode ser escrito facilmente em Angular. No entanto, o **objetivo é usar o componente React**. + +### Dica + +
+ Dica 1 - Configuração + Permita arquivos React no tsconfig.json + +``` +{ +... +"compilerOptions": { + ... + "jsx": "react" +}, +... +} +``` + +
+ +
+ Dica 2 - Initialização + Crie uma raiz react com `createRoot(...)` +
+ +
+ Dica 3 - Visualização + Para renderizar o componente, ele deve parecer com: + ``` + .render( + + ... + + ) + ``` + +
+ +
+ Dica 4 - Design + Não esqueça de permitir o arquivo react no Tailwind. +
From 80420ee1bae427fcd530cb3756b6aabbe60cc3b9 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Sun, 18 Feb 2024 22:10:23 -0300 Subject: [PATCH 029/361] docs(pt): fix typo --- 45-react-in-angular.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45-react-in-angular.md b/45-react-in-angular.md index 896912486..4a07c9691 100644 --- a/45-react-in-angular.md +++ b/45-react-in-angular.md @@ -1,6 +1,6 @@ --- title: 🔴 React em angular -description: Desafio 5 é sobre aprender como se beneficiar das vários bibliotecas em React +description: Desafio 5 é sobre aprender como se beneficiar das várias bibliotecas em React author: wandrille-guesdon challengeNumber: 45 command: angular-react-in-angular From e2df47cd6858d4f3a6bda8d228ac8adee4170e43 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 08:22:38 -0300 Subject: [PATCH 030/361] docs(pt): update challenge 8 text --- .../docs/pt/challenges/angular/8-pipe-pure.md | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md index e50d87831..623eb0b15 100644 --- a/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md @@ -4,18 +4,31 @@ description: Desafio 8 é sobre criar um pipe puro author: thomas-laforge challengeNumber: 8 command: angular-pipe-easy -blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d +blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c40593cd15d sidebar: order: 3 --- -O objetivo desta série de 3 desafios de pipe é dominar **pipe** em Angular. +## Informação -Pipes puros são uma maneira útil de transformar dados do seu template. A diferença entre chamar uma função e um pipe é que pipes puros são cacheados (memoized). Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se sua entrada não for alterada. +Este é o primeiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. -## Informação +Pipes são uma maneira bem poderosa de transformar dados em seu template. A diferença entre chamar uma função e um pipe é que pipes puros são memoizados. Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se suas entradas não mudarem. + +Pipes são eficientes e otimizados para performance. Eles usam mecanismos de detecção de mudanças para apenas recalcular o valor se sua entrada mudar, afim de minimizar cálculos desnecessários e melhorar a performance de renderização. + +Por padrão um pipe é puro, por isso você deve ter cuidado que ao configurar `pipe` como falso deixar mais propenso a ser ineficiente, uma vez que aumenta o número de renderizações. + +:::note[Nota] +Um pipe **puro** é chamado apenas quando o valor muda.\ +Um pipe **impuro** é chamado em cada ciclo da mudança de deteccção. +::: + +Há alguns pipes pré-definidos bem úteis como DatePipe, UpperCasePipe e CurrencyPipe. Para aprender mais sobre pipes em Angular, dê uma olhada na documentação da API [aqui](https://angular.io/guide/pipes). + +## Declaração -Neste primeiro exercício, você chama uma simples função dentro de seu template. O objetivo é convertê-la em um pipe. +Neste exercício, você precisa refatorar uma função de transformação dentro de um componente, o qual é chamado dentro de seu template. O objetivo é converter essa função em um pipe. ## Restrições From cb759c44a726138c99104b467a1706136920bf6d Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 08:25:44 -0300 Subject: [PATCH 031/361] docs(pt): fix blog link typo --- docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md index 623eb0b15..bfbde21a6 100644 --- a/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md +++ b/docs/src/content/docs/pt/challenges/angular/8-pipe-pure.md @@ -4,7 +4,7 @@ description: Desafio 8 é sobre criar um pipe puro author: thomas-laforge challengeNumber: 8 command: angular-pipe-easy -blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c40593cd15d +blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d sidebar: order: 3 --- From f3e4de80d4ffce3bf89d46650156a1d62270a5f9 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 08:43:48 -0300 Subject: [PATCH 032/361] docs(pt): translate challenge 10 --- .../pt/challenges/angular/10-pipe-utility.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md diff --git a/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md new file mode 100644 index 000000000..b26e28826 --- /dev/null +++ b/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md @@ -0,0 +1,34 @@ +--- +title: 🔴 Pipe Empacotador de Utilidade +description: Desafio 10 é sobre a criação de um pipe para empacotar utilidades +author: thomas-laforge +challengeNumber: 10 +command: angular-pipe-hard +sidebar: + order: 202 +--- + +## Informação + +Este é o primeiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. + +Pipes são uma maneira bem poderosa de transformar dados em seu template. A diferença entre chamar uma função e um pipe é que pipes puros são memoizados. Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se suas entradas não mudarem. + +Pipes são eficientes e otimizados para performance. Eles usam mecanismos de detecção de mudanças para apenas recalcular o valor se sua entrada mudar, afim de minimizar cálculos desnecessários e melhorar a performance de renderização. + +Por padrão um pipe é puro, por isso você deve ter cuidado que ao configurar `pipe` como falso deixar mais propenso a ser ineficiente, uma vez que aumenta o número de renderizações. + +:::note[Nota] +Um pipe **puro** é chamado apenas quando o valor muda.\ +Um pipe **impuro** é chamado em cada ciclo da mudança de deteccção. +::: + +Há alguns pipes pré-definidos bem úteis como DatePipe, UpperCasePipe e CurrencyPipe. Para aprender mais sobre pipes em Angular, dê uma olhada na documentação da API [aqui](https://angular.io/guide/pipes). + +## Declaração + +Neste exercício, você quer acessar algumas funções úteis. Atualmente você não consegue acessá-las diretamente do seu template. O objetivo é criar um pipe específico para o arquivo de úteis, e você precisará passar o nome da função que deseja chamar e os argumentos necessários. + +## Restrições + +- Deve ser fortemente tipado From 48972af742fbb2aa2317faf490d9638e7ce064e1 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 08:52:36 -0300 Subject: [PATCH 033/361] docs(pt): translate challenge 9 --- .../pt/challenges/angular/9-pipe-wrapFn.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md diff --git a/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md new file mode 100644 index 000000000..eab2ce737 --- /dev/null +++ b/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md @@ -0,0 +1,35 @@ +--- +title: 🟠 Pipe Empacotador de Função +description: Challenge 9 is about creating a pipe to wrap component fonctions +author: thomas-laforge +challengeNumber: 9 +command: angular-pipe-intermediate +blogLink: https://medium.com/ngconf/boost-your-apps-performance-by-wrapping-your-functions-inside-a-pipe-7e889a901d1d +sidebar: + order: 103 +--- + +## Informação + +Este é o primeiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. + +Pipes são uma maneira bem poderosa de transformar dados em seu template. A diferença entre chamar uma função e um pipe é que pipes puros são memoizados. Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se suas entradas não mudarem. + +Pipes são eficientes e otimizados para performance. Eles usam mecanismos de detecção de mudanças para apenas recalcular o valor se sua entrada mudar, afim de minimizar cálculos desnecessários e melhorar a performance de renderização. + +Por padrão um pipe é puro, por isso você deve ter cuidado que ao configurar `pipe` como falso deixar mais propenso a ser ineficiente, uma vez que aumenta o número de renderizações. + +:::note[Nota] +Um pipe **puro** é chamado apenas quando o valor muda.\ +Um pipe **impuro** é chamado em cada ciclo da mudança de deteccção. +::: + +Há alguns pipes pré-definidos bem úteis como DatePipe, UpperCasePipe e CurrencyPipe. Para aprender mais sobre pipes em Angular, dê uma olhada na documentação da API [aqui](https://angular.io/guide/pipes). + +## Declaração + +Neste exercício, você está chamando várias funções dentro de seu template. Você pode criar um pipe específico para cada uma das funções, mas isso dará muito trabalho. O objetivo é criar um pipe `wrapFn` que empacote sua função callback através do pipe. Sua função DEVE permanecer dentro do seu componentes. **`WrapFn` deve ser reutilizável**. + +## Restrições + +- Deve ser fortemente tipado From 27655cc2231bd1075e9ad0107b9b8b912dfb2625 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 08:59:16 -0300 Subject: [PATCH 034/361] docs(en): fix typo --- docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md index 4d75ef188..562c7cf57 100644 --- a/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/challenges/angular/9-pipe-wrapFn.md @@ -29,7 +29,7 @@ There are some useful predefined pipes like the DatePipe, UpperCasePipe and Curr ## Statement In this exercise, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome. -The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.** +The goal is to create a `wrapFn` pipe to wrap your callback function through a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.** ## Constraints: From 6d496e766c92844c352c381d3a33099ad040c9df Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Mon, 19 Feb 2024 11:54:03 -0300 Subject: [PATCH 035/361] docs(pt): fix challenges set order reference --- docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md | 2 +- docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md b/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md index b26e28826..deaf61de1 100644 --- a/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md +++ b/docs/src/content/docs/pt/challenges/angular/10-pipe-utility.md @@ -10,7 +10,7 @@ sidebar: ## Informação -Este é o primeiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. +Este é o terceiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. Pipes são uma maneira bem poderosa de transformar dados em seu template. A diferença entre chamar uma função e um pipe é que pipes puros são memoizados. Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se suas entradas não mudarem. diff --git a/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md b/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md index eab2ce737..cd06a29ad 100644 --- a/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md +++ b/docs/src/content/docs/pt/challenges/angular/9-pipe-wrapFn.md @@ -11,7 +11,7 @@ sidebar: ## Informação -Este é o primeiro de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. +Este é o segundo de três desafios `@Pipe()`, sendo o objetivo dominar **pipes** em Angular. Pipes são uma maneira bem poderosa de transformar dados em seu template. A diferença entre chamar uma função e um pipe é que pipes puros são memoizados. Por isso, eles não são recalculados em cada ciclo de detecção de mudanças se suas entradas não mudarem. From acd2626f3dbd4d6ebed165c6fbbd7b2bd81b1ea0 Mon Sep 17 00:00:00 2001 From: Stanislav Gavrilov Date: Mon, 19 Feb 2024 20:08:44 +0300 Subject: [PATCH 036/361] docs: add ru translations --- .../ru/challenges/angular/1-projection.md | 43 +++++++++++++++++++ .../challenges/angular/21-achor-scrolling.md | 18 ++++++++ .../angular/4-context-outlet-typed.md | 40 +++++++++++++++++ .../docs/ru/challenges/angular/8-pipe-pure.md | 36 ++++++++++++++++ .../forms/41-control-value-accessor.md | 41 ++++++++++++++++++ docs/src/content/i18n/ru.json | 18 ++++---- 6 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 docs/src/content/docs/ru/challenges/angular/1-projection.md create mode 100644 docs/src/content/docs/ru/challenges/angular/21-achor-scrolling.md create mode 100644 docs/src/content/docs/ru/challenges/angular/4-context-outlet-typed.md create mode 100644 docs/src/content/docs/ru/challenges/angular/8-pipe-pure.md create mode 100644 docs/src/content/docs/ru/challenges/forms/41-control-value-accessor.md diff --git a/docs/src/content/docs/ru/challenges/angular/1-projection.md b/docs/src/content/docs/ru/challenges/angular/1-projection.md new file mode 100644 index 000000000..a08f04671 --- /dev/null +++ b/docs/src/content/docs/ru/challenges/angular/1-projection.md @@ -0,0 +1,43 @@ +--- +title: 🟢 Проекция контента +description: Challenge 1 заключается в изучении проекции элементов DOM через компоненты +author: thomas-laforge +challengeNumber: 1 +command: angular-projection +blogLink: https://medium.com/@thomas.laforge/create-a-highly-customizable-component-cc3a9805e4c5 +videoLink: + link: https://www.youtube.com/watch?v=npyEyUZxoIw&ab_channel=ArthurLannelucq + alt: Projection video by Arthur Lannelucq + flag: FR +sidebar: + order: 1 +--- + +## Информация + +Проекция контента в Angular - это мощная техника для создания компонентов с гибко настраиваемым внешним видом. Понимание и использование концепций ng-content и ngTemplateOutlet может значительно вам помочь создавать компоненты, предназначенные для повторного использования. + +[Здесь](https://angular.io/guide/content-projection#projecting-content-in-more-complex-environments) вы можете изучить все о ng-content, начиная с простых примеров и до более сложных. + +Документацию ngTemplateOutlett, вместе с базовыми примерами, можно найти [тут](https://angular.io/api/common/NgTemplateOutlet). + +Имея эти два инструмента в своем распоряжении, вы теперь готовы пройти испытание. + +## Пояснение + +Вы начнете с полностью работающего приложения, которое включает панель с карточкой учителя и карточкой студента. Цель состоит в том, чтобы реализовать карточку города. + +Хотя приложение работает, его внутреннее устройство далеко от идеала. Каждый раз, когда вам нужно реализовать новую карточку, вам придется изменять `card.component.ts`. В реальных проектах этот компонент может использоваться во многих приложениях. Цель этого упражнения создать `CardComponent`, внешний вид которого можно настроить без каких-либо изменений. После того как вы создадите этот компонент, вы можете создать `CityCardComponent` без модификации `CardComponent`. + +## Ограничения + +- Вы должны провести рефакторинг `CardComponent` и `ListItemComponent`. +- Директива `NgFor` должна быть определена и должна оставаться внутри `CardComponent`, несмотря на возможное желание перенести её в `ParentCardComponent`,как это сделано в `TeacherCardComponent`. +- `CardComponent` не должен содержать `NgIf` или `NgSwitch`. +- CSS: избегайте использования `::ng-deep`. Ищите альтернативные способы стилизации с помощью CSS. + +## Дополнительные задачи + +- Попробуйте использовать новый синтаксис для циклов и условий (документация [тут](https://angular.dev/guide/templates/control-flow)). +- Используйте signal API для управления состоянием компонентов (документация [тут](https://angular.dev/guide/signals)). +- Для ссылки на шаблон используйте директивы вместо магических строк ([What is wrong with magic strings?](https://softwareengineering.stackexchange.com/a/365344)). diff --git a/docs/src/content/docs/ru/challenges/angular/21-achor-scrolling.md b/docs/src/content/docs/ru/challenges/angular/21-achor-scrolling.md new file mode 100644 index 000000000..716f18b8b --- /dev/null +++ b/docs/src/content/docs/ru/challenges/angular/21-achor-scrolling.md @@ -0,0 +1,18 @@ +--- +title: 🟢Навигация по якорю +description: Испытание 21 про навигацию на странице с помощью якоря +author: thomas-laforge +challengeNumber: 21 +command: angular-anchor-scrolling +sidebar: + order: 4 +--- + +## Информация + +Вы начинаете с приложения, которое имеет базовую навигацию и навигацию с использованием якорей в `HomeComponent`. Однако, использование `href` каждый раз создает новый путь и обновляет страницу. + +## Пояснение + +- Ваша задача - рефакторинг этого приложения для использования встроенного инструмента навигации, для более эффективной работы в рамках фреймворка Angular. Вы можете использовать router, но лучше остаться в шаблоне и использовать `RouterLink` директиву. +- Для улучшения пользовательского опыта, добавьте плавную прокрутку. diff --git a/docs/src/content/docs/ru/challenges/angular/4-context-outlet-typed.md b/docs/src/content/docs/ru/challenges/angular/4-context-outlet-typed.md new file mode 100644 index 000000000..053897d78 --- /dev/null +++ b/docs/src/content/docs/ru/challenges/angular/4-context-outlet-typed.md @@ -0,0 +1,40 @@ +--- +title: 🔴 Типизация ContextOutlet +description: Испытание 4 про строгую типизацию ngContextOutlet директивы +author: thomas-laforge +challengeNumber: 4 +command: angular-context-outlet-type +blogLink: https://medium.com/@thomas.laforge/ngtemplateoutlet-type-checking-5d2dcb07a2c6 +sidebar: + order: 201 +--- + +## Информация + +В Angular есть статическая функция [`ngTemplateContextGuard`](https://angular.io/guide/structural-directives#typing-the-directives-context) для строгой типизации структурных директив. + +Однако, контекстом **NgTemplateOutlet** является **Object**. Но с помощью вышеупомянутой гарда, мы можем улучшить это поведение. + +## Пояснение + +В этом испытании, мы хотим научиться строго типизировать ng-template в AppComponent. + +Это упражнение имеет два уровня сложности: + +### Уровень 1: Известный интерфейс + +Сейчас код выглядит следующим образом. + +![Unkown Person](../../../../../assets/4/unknown-person.png 'Unkown Person') + +Как мы видим, у переменной name тип "any". Мы хотим вывести правильный тип. + +### Уровень 2: Обобщённый интерфейс + +Сейчас код выглядит следующим образом. + +![Unkown Student](../../../../../assets/4/unknown-student.png 'Unkown Student') + +Как мы видим, у переменной student тип "any". Мы хотим вывести правильный тип. + +Но на этот раз, мы хотим передавать в `ListComponent` список из любых объектов. И мы все равно хотим, чтобы был выведен правильный тип. diff --git a/docs/src/content/docs/ru/challenges/angular/8-pipe-pure.md b/docs/src/content/docs/ru/challenges/angular/8-pipe-pure.md new file mode 100644 index 000000000..7d8067abb --- /dev/null +++ b/docs/src/content/docs/ru/challenges/angular/8-pipe-pure.md @@ -0,0 +1,36 @@ +--- +title: 🟢Чистый пайп +description: Испытание 8 про создание чистого пайпа +author: thomas-laforge +challengeNumber: 8 +command: angular-pipe-easy +blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d +sidebar: + order: 3 +--- + +## Информация + +This is the first of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular. +Это первое испытание про `@Pipe()` из трех, цель этой серии испытаний - освоить работу с **pipes** в Angular. + +Пайпы - удобный способ трансформации данных в вашем шаблоне. Разница между вызовом функции и пайпом заключается в том, что результат, возвращаемый чистыми пайпами, кэшируется. Таким образом, они не будут пересчитываться при каждом цикле обнаружения изменений, если их входные значения не изменились. + +Pipes разработаны так, чтобы быть эффективными и оптимизированными для производительности. Они используют механизмы обнаружения изменений, чтобы пересчитывать значение только в случае изменения входных данных, минимизируя ненужные вычисления и улучшая производительность рендеринга. + +По умолчанию пайпы чистые, но вы должны знать, что установка `pure` в false может привести к неэффективности, поскольку это увеличивает количество перерисовок. + +:::note[Примечание] +**Чистые** пайп вызывается только когда изменяется входное значение.\ +**Нечистый** пайп вызывается на каждый цикл обнаружения изменений. +::: + +Существуют несколько полезных предопределенных пайпов, таких как DatePipe, UpperCasePipe и CurrencyPipe. Чтобы узнать больше о пайпах в Angular, ознакомьтесь с документацией API [здесь](https://angular.io/guide/pipes). + +## Пояснение + +В этом упражнении необходимо превратить вызов функции в шаблоне в использование пайпа. + +## Ограничение + +- Пайп должен быть типизирован. diff --git a/docs/src/content/docs/ru/challenges/forms/41-control-value-accessor.md b/docs/src/content/docs/ru/challenges/forms/41-control-value-accessor.md new file mode 100644 index 000000000..98659a936 --- /dev/null +++ b/docs/src/content/docs/ru/challenges/forms/41-control-value-accessor.md @@ -0,0 +1,41 @@ +--- +title: 🟠 Control Value Accessor +description: Испытание 41 про создание пользовательское поле формы которое использует интерфейс ControlValueAccessor. +author: stanislav-gavrilov +challengeNumber: 41 +command: forms-control-value-accessor +sidebar: + order: 1 +--- + +## Информация + +Цель этого испытания создать пользовательское поле формы, которое использует API формы Angular через `ControlValueAccessor`. Документацию можно посмотреть [здесь](https://angular.io/api/forms/ControlValueAccessor). Этот интерфейс критически важен для создания пользовательских элементов управления формами, которые могут беспрепятственно взаимодействовать с API форм Angular. + +## Пояснение + +Задача - использовать контрол в `feedbackForm` напрямую, чтобы убрать необходимость в использовании `@Output` для получения значения из `app-rating-control` и установки его в `FormGroup`. +Кроме того, вы должны добавить валидацию для нового элемента управления, чтобы гарантировать наличие данных о рейтинге. (Кнопка отправки формы должна быть отключена, если форма недействительна). + +Сейчас компонент рейтинга используется следующим образом: + +```html + +``` + +```ts +rating: string | null = null; + +onFormSubmit(): void { + this.feedBackSubmit.emit({ + ...this.feedbackForm.value, + rating: this.rating, // not inside the FormGroup and no validation + }); +} +``` + +Необходимо, чтобы компонент можно было использовать так: + +```html + +``` diff --git a/docs/src/content/i18n/ru.json b/docs/src/content/i18n/ru.json index 9595ba21d..0e8155756 100644 --- a/docs/src/content/i18n/ru.json +++ b/docs/src/content/i18n/ru.json @@ -1,10 +1,10 @@ { "page.title.challenge": "Испытание", "author.createdBy": "Создано", - "buttons.email": "Email subscription", - "buttons.star": "Дать звезду", - "buttons.sponsor": "Спонсор", - "buttons.clipboardCopy": "Copied!", + "buttons.email": "Подписаться на email рассылку", + "buttons.star": "Добавить звезду", + "buttons.sponsor": "Спонсировать", + "buttons.clipboardCopy": "Скопировано!", "404.text": "Страница не найдена. Проверьте URL-адрес или воспользуйтесь строкой поиска.", "challenge.footer.note": "Примечание", "challenge.footer.running": "Запустите проект, выполнив команду:", @@ -13,12 +13,12 @@ "challenge.footer.communityAnswers": "Решения сообщества", "challenge.footer.authorAnswer": "Решение автора", "challenge.footer.blogPost": "Статья", - "challenge.footer.video": "Video", + "challenge.footer.video": "Видео", "challenge.footer.gettingStarted.title": "Чтобы пройти это испытание, прочитайте:", "challenge.footer.gettingStarted.link": "Первые шаги", - "challenge.footer.upvoteAnswer": "You can upvote an answer with a 👍 if you like it", - "subscription.button": "Subscribe", + "challenge.footer.upvoteAnswer": "Вы можете проголосовать за этот ответ 👍 если он вам понравился", + "subscription.button": "Подписаться", "subscription.email": "username@gmail.com", - "subscription.note.title": "Notes", - "subscription.note.description": "This email will only be used for sending new challenges updates" + "subscription.note.title": "Примечание", + "subscription.note.description": "Этот email будет использоваться только для о новых испытаниях" } From cc4d34fce040753e78bb1e185626ba070b5cd222 Mon Sep 17 00:00:00 2001 From: Stanislav Gavrilov Date: Mon, 19 Feb 2024 20:16:40 +0300 Subject: [PATCH 037/361] docs: fix typo --- docs/src/content/i18n/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/i18n/ru.json b/docs/src/content/i18n/ru.json index 0e8155756..be1716a4c 100644 --- a/docs/src/content/i18n/ru.json +++ b/docs/src/content/i18n/ru.json @@ -20,5 +20,5 @@ "subscription.button": "Подписаться", "subscription.email": "username@gmail.com", "subscription.note.title": "Примечание", - "subscription.note.description": "Этот email будет использоваться только для о новых испытаниях" + "subscription.note.description": "Этот email будет использоваться только для сообщений о новых испытаниях" } From 649eb847bee844501ae336e8bcfd211b983c1861 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Mon, 19 Feb 2024 23:39:09 +0100 Subject: [PATCH 038/361] feat: challenge 45 Simple Animations --- README.md | 2 +- apps/angular/simple-animations/.eslintrc.json | 36 ++++++++ apps/angular/simple-animations/README.md | 13 +++ apps/angular/simple-animations/jest.config.ts | 22 +++++ apps/angular/simple-animations/project.json | 80 ++++++++++++++++++ .../src/app/app.component.spec.ts | 8 ++ .../src/app/app.component.ts | 78 +++++++++++++++++ .../simple-animations/src/app/app.config.ts | 5 ++ .../simple-animations/src/assets/.gitkeep | 0 .../angular/simple-animations/src/favicon.ico | Bin 0 -> 15086 bytes apps/angular/simple-animations/src/index.html | 13 +++ apps/angular/simple-animations/src/main.ts | 7 ++ .../angular/simple-animations/src/styles.scss | 5 ++ .../simple-animations/src/test-setup.ts | 2 + .../simple-animations/tailwind.config.js | 14 +++ .../simple-animations/tsconfig.app.json | 10 +++ .../simple-animations/tsconfig.editor.json | 7 ++ apps/angular/simple-animations/tsconfig.json | 33 ++++++++ .../simple-animations/tsconfig.spec.json | 15 ++++ challenge-number.json | 4 +- .../challenges/angular/44-view-transition.md | 1 - .../angular/45-simple-animations.md | 38 +++++++++ docs/src/content/docs/es/index.mdx | 13 +-- docs/src/content/docs/fr/index.mdx | 10 +-- docs/src/content/docs/index.mdx | 9 +- docs/src/content/docs/pt/index.mdx | 15 ++-- docs/src/content/docs/ru/index.mdx | 33 ++++---- 27 files changed, 431 insertions(+), 42 deletions(-) create mode 100644 apps/angular/simple-animations/.eslintrc.json create mode 100644 apps/angular/simple-animations/README.md create mode 100644 apps/angular/simple-animations/jest.config.ts create mode 100644 apps/angular/simple-animations/project.json create mode 100644 apps/angular/simple-animations/src/app/app.component.spec.ts create mode 100644 apps/angular/simple-animations/src/app/app.component.ts create mode 100644 apps/angular/simple-animations/src/app/app.config.ts create mode 100644 apps/angular/simple-animations/src/assets/.gitkeep create mode 100644 apps/angular/simple-animations/src/favicon.ico create mode 100644 apps/angular/simple-animations/src/index.html create mode 100644 apps/angular/simple-animations/src/main.ts create mode 100644 apps/angular/simple-animations/src/styles.scss create mode 100644 apps/angular/simple-animations/src/test-setup.ts create mode 100644 apps/angular/simple-animations/tailwind.config.js create mode 100644 apps/angular/simple-animations/tsconfig.app.json create mode 100644 apps/angular/simple-animations/tsconfig.editor.json create mode 100644 apps/angular/simple-animations/tsconfig.json create mode 100644 apps/angular/simple-animations/tsconfig.spec.json create mode 100644 docs/src/content/docs/challenges/angular/45-simple-animations.md diff --git a/README.md b/README.md index 1e43bdfef..de881440c 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 44 challenges](https://angular-challenges.vercel.app/) +Check [all 45 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ diff --git a/apps/angular/simple-animations/.eslintrc.json b/apps/angular/simple-animations/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/angular/simple-animations/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/simple-animations/README.md b/apps/angular/simple-animations/README.md new file mode 100644 index 000000000..f151448d2 --- /dev/null +++ b/apps/angular/simple-animations/README.md @@ -0,0 +1,13 @@ +# Simple Animations + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-simple-animations +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/45-simple-animations/). diff --git a/apps/angular/simple-animations/jest.config.ts b/apps/angular/simple-animations/jest.config.ts new file mode 100644 index 000000000..8f5d36cf8 --- /dev/null +++ b/apps/angular/simple-animations/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-simple-animations', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/simple-animations', + 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/angular/simple-animations/project.json b/apps/angular/simple-animations/project.json new file mode 100644 index 000000000..4ba302da8 --- /dev/null +++ b/apps/angular/simple-animations/project.json @@ -0,0 +1,80 @@ +{ + "name": "angular-simple-animations", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/simple-animations/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/simple-animations", + "index": "apps/angular/simple-animations/src/index.html", + "browser": "apps/angular/simple-animations/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/simple-animations/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/simple-animations/src/favicon.ico", + "apps/angular/simple-animations/src/assets" + ], + "styles": ["apps/angular/simple-animations/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-simple-animations:build:production" + }, + "development": { + "buildTarget": "angular-simple-animations:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-simple-animations:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "apps/angular/simple-animations/jest.config.ts" + } + } + } +} diff --git a/apps/angular/simple-animations/src/app/app.component.spec.ts b/apps/angular/simple-animations/src/app/app.component.spec.ts new file mode 100644 index 000000000..3905d62a4 --- /dev/null +++ b/apps/angular/simple-animations/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/angular/simple-animations/src/app/app.component.ts b/apps/angular/simple-animations/src/app/app.component.ts new file mode 100644 index 000000000..c194f4a18 --- /dev/null +++ b/apps/angular/simple-animations/src/app/app.component.ts @@ -0,0 +1,78 @@ +import { Component } from '@angular/core'; + +@Component({ + standalone: true, + imports: [], + selector: 'app-root', + template: ` +
+
+
+

2008

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+ +
+

2010

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+ +
+

2012

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+
+ +
+
+
+
Name:
+
Samuel
+
+ +
+
Age:
+
28
+
+ +
+
Birthdate:
+
02.11.1995
+
+ +
+
City:
+
Berlin
+
+ +
+
Language:
+
English
+
+ +
+
Like Pizza:
+
Hell yeah
+
+
+
+
+ `, + styles: [''], +}) +export class AppComponent {} diff --git a/apps/angular/simple-animations/src/app/app.config.ts b/apps/angular/simple-animations/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/angular/simple-animations/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/angular/simple-animations/src/assets/.gitkeep b/apps/angular/simple-animations/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/angular/simple-animations/src/favicon.ico b/apps/angular/simple-animations/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 zcmeI332;U^%p|z7g|#(P)qFEA@4f!_@qOK2 z_lJl}!lhL!VT_U|uN7%8B2iKH??xhDa;*`g{yjTFWHvXn;2s{4R7kH|pKGdy(7z!K zgftM+Ku7~24TLlh(!g)gz|foI94G^t2^IO$uvX$3(OR0<_5L2sB)lMAMy|+`xodJ{ z_Uh_1m)~h?a;2W{dmhM;u!YGo=)OdmId_B<%^V^{ovI@y`7^g1_V9G}*f# zNzAtvou}I!W1#{M^@ROc(BZ! z+F!!_aR&Px3_reO(EW+TwlW~tv*2zr?iP7(d~a~yA|@*a89IUke+c472NXM0wiX{- zl`UrZC^1XYyf%1u)-Y)jj9;MZ!SLfd2Hl?o|80Su%Z?To_=^g_Jt0oa#CT*tjx>BI z16wec&AOWNK<#i0Qd=1O$fymLRoUR*%;h@*@v7}wApDl^w*h}!sYq%kw+DKDY)@&A z@9$ULEB3qkR#85`lb8#WZw=@})#kQig9oqy^I$dj&k4jU&^2(M3q{n1AKeGUKPFbr z1^<)aH;VsG@J|B&l>UtU#Ejv3GIqERzYgL@UOAWtW<{p#zy`WyJgpCy8$c_e%wYJL zyGHRRx38)HyjU3y{-4z6)pzb>&Q1pR)B&u01F-|&Gx4EZWK$nkUkOI|(D4UHOXg_- zw{OBf!oWQUn)Pe(=f=nt=zkmdjpO^o8ZZ9o_|4tW1ni+Un9iCW47*-ut$KQOww!;u z`0q)$s6IZO!~9$e_P9X!hqLxu`fpcL|2f^I5d4*a@Dq28;@2271v_N+5HqYZ>x;&O z05*7JT)mUe&%S0@UD)@&8SmQrMtsDfZT;fkdA!r(S=}Oz>iP)w=W508=Rc#nNn7ym z1;42c|8($ALY8#a({%1#IXbWn9-Y|0eDY$_L&j{63?{?AH{);EzcqfydD$@-B`Y3<%IIj7S7rK_N}je^=dEk%JQ4c z!tBdTPE3Tse;oYF>cnrapWq*o)m47X1`~6@(!Y29#>-#8zm&LXrXa(3=7Z)ElaQqj z-#0JJy3Fi(C#Rx(`=VXtJ63E2_bZGCz+QRa{W0e2(m3sI?LOcUBx)~^YCqZ{XEPX)C>G>U4tfqeH8L(3|pQR*zbL1 zT9e~4Tb5p9_G}$y4t`i*4t_Mr9QYvL9C&Ah*}t`q*}S+VYh0M6GxTTSXI)hMpMpIq zD1ImYqJLzbj0}~EpE-aH#VCH_udYEW#`P2zYmi&xSPs_{n6tBj=MY|-XrA;SGA_>y zGtU$?HXm$gYj*!N)_nQ59%lQdXtQZS3*#PC-{iB_sm+ytD*7j`D*k(P&IH2GHT}Eh z5697eQECVIGQAUe#eU2I!yI&%0CP#>%6MWV z@zS!p@+Y1i1b^QuuEF*13CuB zu69dve5k7&Wgb+^s|UB08Dr3u`h@yM0NTj4h7MnHo-4@xmyr7(*4$rpPwsCDZ@2be zRz9V^GnV;;?^Lk%ynzq&K(Aix`mWmW`^152Hoy$CTYVehpD-S1-W^#k#{0^L`V6CN+E z!w+xte;2vu4AmVNEFUOBmrBL>6MK@!O2*N|2=d|Y;oN&A&qv=qKn73lDD zI(+oJAdgv>Yr}8(&@ZuAZE%XUXmX(U!N+Z_sjL<1vjy1R+1IeHt`79fnYdOL{$ci7 z%3f0A*;Zt@ED&Gjm|OFTYBDe%bbo*xXAQsFz+Q`fVBH!N2)kaxN8P$c>sp~QXnv>b zwq=W3&Mtmih7xkR$YA)1Yi?avHNR6C99!u6fh=cL|KQ&PwF!n@ud^n(HNIImHD!h87!i*t?G|p0o+eelJ?B@A64_9%SBhNaJ64EvKgD&%LjLCYnNfc; znj?%*p@*?dq#NqcQFmmX($wms@CSAr9#>hUR^=I+=0B)vvGX%T&#h$kmX*s=^M2E!@N9#m?LhMvz}YB+kd zG~mbP|D(;{s_#;hsKK9lbVK&Lo734x7SIFJ9V_}2$@q?zm^7?*XH94w5Qae{7zOMUF z^?%F%)c1Y)Q?Iy?I>knw*8gYW#ok|2gdS=YYZLiD=CW|Nj;n^x!=S#iJ#`~Ld79+xXpVmUK^B(xO_vO!btA9y7w3L3-0j-y4 z?M-V{%z;JI`bk7yFDcP}OcCd*{Q9S5$iGA7*E1@tfkyjAi!;wP^O71cZ^Ep)qrQ)N z#wqw0_HS;T7x3y|`P==i3hEwK%|>fZ)c&@kgKO1~5<5xBSk?iZV?KI6&i72H6S9A* z=U(*e)EqEs?Oc04)V-~K5AUmh|62H4*`UAtItO$O(q5?6jj+K^oD!04r=6#dsxp?~}{`?&sXn#q2 zGuY~7>O2=!u@@Kfu7q=W*4egu@qPMRM>(eyYyaIE<|j%d=iWNdGsx%c!902v#ngNg z@#U-O_4xN$s_9?(`{>{>7~-6FgWpBpqXb`Ydc3OFL#&I}Irse9F_8R@4zSS*Y*o*B zXL?6*Aw!AfkNCgcr#*yj&p3ZDe2y>v$>FUdKIy_2N~}6AbHc7gA3`6$g@1o|dE>vz z4pl(j9;kyMsjaw}lO?(?Xg%4k!5%^t#@5n=WVc&JRa+XT$~#@rldvN3S1rEpU$;XgxVny7mki3 z-Hh|jUCHrUXuLr!)`w>wgO0N%KTB-1di>cj(x3Bav`7v z3G7EIbU$z>`Nad7Rk_&OT-W{;qg)-GXV-aJT#(ozdmnA~Rq3GQ_3mby(>q6Ocb-RgTUhTN)))x>m&eD;$J5Bg zo&DhY36Yg=J=$Z>t}RJ>o|@hAcwWzN#r(WJ52^g$lh^!63@hh+dR$&_dEGu&^CR*< z!oFqSqO@>xZ*nC2oiOd0eS*F^IL~W-rsrO`J`ej{=ou_q^_(<$&-3f^J z&L^MSYWIe{&pYq&9eGaArA~*kA + + + + angular-simple-animations + + + + + + + + diff --git a/apps/angular/simple-animations/src/main.ts b/apps/angular/simple-animations/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/simple-animations/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/simple-animations/src/styles.scss b/apps/angular/simple-animations/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/angular/simple-animations/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/angular/simple-animations/src/test-setup.ts b/apps/angular/simple-animations/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/angular/simple-animations/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/angular/simple-animations/tailwind.config.js b/apps/angular/simple-animations/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/angular/simple-animations/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/angular/simple-animations/tsconfig.app.json b/apps/angular/simple-animations/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/angular/simple-animations/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/angular/simple-animations/tsconfig.editor.json b/apps/angular/simple-animations/tsconfig.editor.json new file mode 100644 index 000000000..8ae117d96 --- /dev/null +++ b/apps/angular/simple-animations/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/angular/simple-animations/tsconfig.json b/apps/angular/simple-animations/tsconfig.json new file mode 100644 index 000000000..7a9f4b7a7 --- /dev/null +++ b/apps/angular/simple-animations/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "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/angular/simple-animations/tsconfig.spec.json b/apps/angular/simple-animations/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/angular/simple-animations/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 a48a4f1cb..95430ce0a 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,6 +1,6 @@ { - "total": 44, - "🟢": 16, + "total": 45, + "🟢": 17, "🟠": 120, "🔴": 208 } diff --git a/docs/src/content/docs/challenges/angular/44-view-transition.md b/docs/src/content/docs/challenges/angular/44-view-transition.md index 46ae58010..6dbf21131 100644 --- a/docs/src/content/docs/challenges/angular/44-view-transition.md +++ b/docs/src/content/docs/challenges/angular/44-view-transition.md @@ -6,7 +6,6 @@ challengeNumber: 44 command: angular-view-transition sidebar: order: 208 - badge: New --- ## Information diff --git a/docs/src/content/docs/challenges/angular/45-simple-animations.md b/docs/src/content/docs/challenges/angular/45-simple-animations.md new file mode 100644 index 000000000..839872b29 --- /dev/null +++ b/docs/src/content/docs/challenges/angular/45-simple-animations.md @@ -0,0 +1,38 @@ +--- +title: 🟢 Simple Animations +description: Challenge 45 is about learning angular's integrated animation API +author: sven-brodny +challengeNumber: 45 +command: angular-simple-animations +sidebar: + order: 17 + badge: New +--- + +## Information + +Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. Animations can improve your application and user experience in a number of ways: + +- Without animations, web page transitions can seem abrupt and jarring +- Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions +- Good animations intuitively call the user's attention to where it is needed + +I would recommend you to read the [official documentation](https://angular.io/guide/animations). You will learn everything that is necessary to successfully complete the challenge. + +Otherwise look at this [working example](https://svenson95.github.io/ng-xmp-animations/) and [git repo](https://github.com/svenson95/ng-xmp-animations) to get inspired. + +## Statement + +The goal of this challenge is to add animations. + +## Constraints + +Don't use any css and utilize angular's integrated `@angular/animations` api. + +### Level 1 + +Add a fading or moving animation for the paragraphs on the left side + +### Level 2 + +Add a stagger animation for the list on the right side diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index e164844f8..12241fda1 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir al Desafío más reciente - link: /es/challenges/angular/43-signal-input/ + link: /es/challenges/angular/45-simple-animations/ icon: rocket - text: Dar una estrella link: https://github.com/tomalaforge/angular-challenges @@ -23,16 +23,16 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositorio contiene 44 desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. + + Este repositorio contiene 45 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades. - + @@ -57,7 +57,8 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro' - Completar estos desafíos te preparará para cualquier desafío técnico que puedas encontrar en un rol de frontend durante las entrevistas. + Completar estos desafíos te preparará para cualquier desafío técnico que + puedas encontrar en un rol de frontend durante las entrevistas. diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index 892cda6c4..ae334e576 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -15,7 +15,7 @@ hero: icon: right-arrow variant: primary - text: Aller au dernier Challenge - link: /fr/challenges/angular/44-view-transition/ + link: /fr/challenges/angular/45-simple-animations/ icon: rocket - text: Donne une étoile link: https://github.com/tomalaforge/angular-challenges @@ -25,15 +25,15 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Ce répertoire rassemble 44 défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. + + Ce répertoire rassemble 45 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. - + diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 968084a93..7185c30a3 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -24,17 +24,16 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../components/MyIcon.astro'; -import SubscriptionForm from '../../components/SubscriptionForm.astro' - +import SubscriptionForm from '../../components/SubscriptionForm.astro'; - - This repository gathers 44 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. + + This repository gathers 45 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. These challenges resolve around real-life issues or specific features to elevate your skills. - + diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx index 3004dae3c..3b2c19887 100644 --- a/docs/src/content/docs/pt/index.mdx +++ b/docs/src/content/docs/pt/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir para o desafio mais recente - link: /pt/challenges/angular/44-view-transition/ + link: /pt/challenges/angular/45-simple-animations/ icon: rocket - text: Dar uma estrela link: https://github.com/tomalaforge/angular-challenges @@ -23,19 +23,20 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositório possui 44 desafios relacionados a Angular, Nx, RxJS, + + Este repositório possui 45 Desafios relacionados a Angular, Nx, RxJS, Ngrx e Typescript. Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de melhorar suas habilidades. - - - +{' '} + + + {' '} diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx index ac0cb90b9..15f96ce83 100644 --- a/docs/src/content/docs/ru/index.mdx +++ b/docs/src/content/docs/ru/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Перейти к последней задаче - link: /ru/challenges/angular/44-view-transition/ + link: /ru/challenges/angular/45-simple-animations/ icon: rocket - text: Добавить звезду link: https://github.com/tomalaforge/angular-challenges @@ -23,36 +23,38 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components'; import MyIcon from '../../../components/MyIcon.astro'; -import SubscriptionForm from '../../../components/SubscriptionForm.astro' +import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Этот репозиторий содержит 44 испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. + + Этот репозиторий содержит 45 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас. - + - Одна из целей этого репозитория снизить барьер для разработки - открытого программного обеспечения (OSS). Решив эти задачи, вы поймете, - как начать вносить свой вклад в любой другой проект с открытым исходным кодом. + Одна из целей этого репозитория снизить барьер для разработки открытого + программного обеспечения (OSS). Решив эти задачи, вы поймете, как начать + вносить свой вклад в любой другой проект с открытым исходным кодом. - Изучение и использование нового фреймворка всегда сопряжено с трудностями. - В этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на практике то, чему вы научились. - Любой может оставить комментарий или предложить помощь. + Изучение и использование нового фреймворка всегда сопряжено с трудностями. В + этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на + практике то, чему вы научились. Любой может оставить комментарий или + предложить помощь. - Учиться одному - здорово, но обучение вместе с другими поможет вам добиться большего. + Учиться одному - здорово, но обучение вместе с другими поможет вам добиться + большего. У вас есть идея или интересный баг? Не стесняйтесь;{' '} - Создавайте свои собственные испытания не теряя времени. + Создавайте свои собственные испытания не теряя времени. @@ -61,8 +63,9 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro' - Это бесплатный проект, и он будет оставаться таковым как можно дольше. - Однако вся работа ведется в мое свободное время, включая создание новых испытаний и ревью их решений(PRs). + Это бесплатный проект, и он будет оставаться таковым как можно дольше. Однако + вся работа ведется в мое свободное время, включая создание новых испытаний и + ревью их решений(PRs). Спонсорство может поддержать меня и способствовать развитию проекта. From 93b27177753d02d3ff17ef4fb8dc86b178ef0254 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Mon, 19 Feb 2024 23:58:41 +0100 Subject: [PATCH 039/361] refactor: simple animations challenge template --- .../src/app/app.component.ts | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/apps/angular/simple-animations/src/app/app.component.ts b/apps/angular/simple-animations/src/app/app.component.ts index c194f4a18..f3d710e33 100644 --- a/apps/angular/simple-animations/src/app/app.component.ts +++ b/apps/angular/simple-animations/src/app/app.component.ts @@ -4,11 +4,24 @@ import { Component } from '@angular/core'; standalone: true, imports: [], selector: 'app-root', + styles: ` + .column { + @apply flex flex-1 flex-col gap-5; + } + + .list-item { + @apply flex flex-row border-b px-5 pb-2; + + span { + @apply flex-1; + } + } + `, template: `
-
+
-

2008

+

2008

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae mollitia sequi accusantium, distinctio similique laudantium eveniet @@ -18,7 +31,7 @@ import { Component } from '@angular/core';

-

2010

+

2010

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae mollitia sequi accusantium, distinctio similique laudantium eveniet @@ -28,7 +41,7 @@ import { Component } from '@angular/core';

-

2012

+

2012

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae mollitia sequi accusantium, distinctio similique laudantium eveniet @@ -38,41 +51,38 @@ import { Component } from '@angular/core';

-
-
-
-
Name:
-
Samuel
-
+
+
+ Name: + Samuel +
-
-
Age:
-
28
-
+
+ Age: + 28 +
-
-
Birthdate:
-
02.11.1995
-
+
+ Birthdate: + 02.11.1995 +
-
-
City:
-
Berlin
-
+
+ City: + Berlin +
-
-
Language:
-
English
-
+
+ Language: + English +
-
-
Like Pizza:
-
Hell yeah
-
+
+ Like Pizza: + Hell yeah
`, - styles: [''], }) export class AppComponent {} From 11106df4f49b4a38d11a468bbf4a28d99680539a Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 00:26:31 +0100 Subject: [PATCH 040/361] refactor: simple animations challenge template & delete spec --- .../src/app/app.component.spec.ts | 8 ------- .../src/app/app.component.ts | 22 +++++++++---------- 2 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 apps/angular/simple-animations/src/app/app.component.spec.ts diff --git a/apps/angular/simple-animations/src/app/app.component.spec.ts b/apps/angular/simple-animations/src/app/app.component.spec.ts deleted file mode 100644 index 3905d62a4..000000000 --- a/apps/angular/simple-animations/src/app/app.component.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { render } from '@testing-library/angular'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - test('...', async () => { - await render(AppComponent); - }); -}); diff --git a/apps/angular/simple-animations/src/app/app.component.ts b/apps/angular/simple-animations/src/app/app.component.ts index f3d710e33..9f537b3fb 100644 --- a/apps/angular/simple-animations/src/app/app.component.ts +++ b/apps/angular/simple-animations/src/app/app.component.ts @@ -5,7 +5,7 @@ import { Component } from '@angular/core'; imports: [], selector: 'app-root', styles: ` - .column { + section { @apply flex flex-1 flex-col gap-5; } @@ -19,8 +19,8 @@ import { Component } from '@angular/core'; `, template: `
-
-
+
+

2008

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae @@ -28,9 +28,9 @@ import { Component } from '@angular/core'; quidem sit placeat possimus tempore dolorum inventore corporis atque quae ad, nobis explicabo delectus.

-
+
-
+

2010

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae @@ -38,9 +38,9 @@ import { Component } from '@angular/core'; quidem sit placeat possimus tempore dolorum inventore corporis atque quae ad, nobis explicabo delectus.

-
+
-
+

2012

Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae @@ -48,10 +48,10 @@ import { Component } from '@angular/core'; quidem sit placeat possimus tempore dolorum inventore corporis atque quae ad, nobis explicabo delectus.

-
-
+
+ -
+
Name: Samuel @@ -81,7 +81,7 @@ import { Component } from '@angular/core'; Like Pizza: Hell yeah
-
+
`, }) From 022f997de81e008c96ed90064970d75e1e5130a3 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 08:05:30 +0100 Subject: [PATCH 041/361] fix(simple-animations): wrong author, challenge number & typos --- apps/angular/simple-animations/README.md | 4 ++-- challenge-number.json | 2 +- .../challenges/angular/45-simple-animations.md | 16 ++++++++-------- docs/src/content/docs/es/index.mdx | 2 +- docs/src/content/docs/fr/index.mdx | 2 +- docs/src/content/docs/pt/index.mdx | 3 ++- docs/src/content/docs/ru/index.mdx | 2 +- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/apps/angular/simple-animations/README.md b/apps/angular/simple-animations/README.md index f151448d2..87e6c7e7c 100644 --- a/apps/angular/simple-animations/README.md +++ b/apps/angular/simple-animations/README.md @@ -1,6 +1,6 @@ # Simple Animations -> author: thomas-laforge +> author: sven-brodny ### Run Application @@ -10,4 +10,4 @@ npx nx serve angular-simple-animations ### Documentation and Instruction -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/45-simple-animations/). +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/46-simple-animations/). diff --git a/challenge-number.json b/challenge-number.json index 21805a067..bba17af31 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,5 +1,5 @@ { - "total": 45, + "total": 46, "🟢": 17, "🟠": 120, "🔴": 209 diff --git a/docs/src/content/docs/challenges/angular/45-simple-animations.md b/docs/src/content/docs/challenges/angular/45-simple-animations.md index 839872b29..29edaafb4 100644 --- a/docs/src/content/docs/challenges/angular/45-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/45-simple-animations.md @@ -1,8 +1,8 @@ --- title: 🟢 Simple Animations -description: Challenge 45 is about learning angular's integrated animation API +description: Challenge 46 is about learning Angular's integrated animation API author: sven-brodny -challengeNumber: 45 +challengeNumber: 46 command: angular-simple-animations sidebar: order: 17 @@ -13,9 +13,9 @@ sidebar: Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. Animations can improve your application and user experience in a number of ways: -- Without animations, web page transitions can seem abrupt and jarring -- Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions -- Good animations intuitively call the user's attention to where it is needed +- Without animations, web page transitions can seem abrupt and jarring. +- Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions. +- Good animations intuitively call the user's attention to where it is needed. I would recommend you to read the [official documentation](https://angular.io/guide/animations). You will learn everything that is necessary to successfully complete the challenge. @@ -27,12 +27,12 @@ The goal of this challenge is to add animations. ## Constraints -Don't use any css and utilize angular's integrated `@angular/animations` api. +Don't use any CSS and utilize Angular's integrated `@angular/animations` API. ### Level 1 -Add a fading or moving animation for the paragraphs on the left side +Add a fading or moving animation for the paragraphs on the left side. ### Level 2 -Add a stagger animation for the list on the right side +Add a stagger animation for the list on the right side. diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index 12241fda1..f0b6d2a7a 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir al Desafío más reciente - link: /es/challenges/angular/45-simple-animations/ + link: /es/challenges/angular/46-simple-animations/ icon: rocket - text: Dar una estrella link: https://github.com/tomalaforge/angular-challenges diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index ae334e576..3f059637a 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -15,7 +15,7 @@ hero: icon: right-arrow variant: primary - text: Aller au dernier Challenge - link: /fr/challenges/angular/45-simple-animations/ + link: /fr/challenges/angular/46-simple-animations/ icon: rocket - text: Donne une étoile link: https://github.com/tomalaforge/angular-challenges diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx index 3b2c19887..f1c14ee87 100644 --- a/docs/src/content/docs/pt/index.mdx +++ b/docs/src/content/docs/pt/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir para o desafio mais recente - link: /pt/challenges/angular/45-simple-animations/ + link: /pt/challenges/angular/46-simple-animations/ icon: rocket - text: Dar uma estrela link: https://github.com/tomalaforge/angular-challenges @@ -34,6 +34,7 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro';
{' '} + diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx index 15f96ce83..3e25ab430 100644 --- a/docs/src/content/docs/ru/index.mdx +++ b/docs/src/content/docs/ru/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Перейти к последней задаче - link: /ru/challenges/angular/45-simple-animations/ + link: /ru/challenges/angular/46-simple-animations/ icon: rocket - text: Добавить звезду link: https://github.com/tomalaforge/angular-challenges From 2cfee0ff48e0f8916e18bd8275f7bbfe8b5f0ab3 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 08:13:16 +0100 Subject: [PATCH 042/361] fix(simple-animations): file name with wrong challenge number --- .../angular/{45-simple-animations.md => 46-simple-animations.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/src/content/docs/challenges/angular/{45-simple-animations.md => 46-simple-animations.md} (100%) diff --git a/docs/src/content/docs/challenges/angular/45-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md similarity index 100% rename from docs/src/content/docs/challenges/angular/45-simple-animations.md rename to docs/src/content/docs/challenges/angular/46-simple-animations.md From 070f0ff6ee5aedb102c3b530a41f333044fde784 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 08:14:09 +0100 Subject: [PATCH 043/361] fix(simple-animations): wrong challenge numbers & wrong latest challenge --- README.md | 2 +- docs/src/content/docs/es/index.mdx | 4 ++-- docs/src/content/docs/fr/index.mdx | 4 ++-- docs/src/content/docs/index.mdx | 6 +++--- docs/src/content/docs/pt/index.mdx | 4 ++-- docs/src/content/docs/ru/index.mdx | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a35021200..8d4d9a069 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 45 challenges](https://angular-challenges.vercel.app/) +Check [all 46 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index f0b6d2a7a..deb834078 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositorio contiene 45 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. + + Este repositorio contiene 46 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades. diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index 3f059637a..d24f92a88 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -28,8 +28,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Ce répertoire rassemble 45 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. + + Ce répertoire rassemble 46 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index b9a57157f..a17253336 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Go to the latest Challenge - link: /challenges/angular/45-react-in-angular/ + link: /challenges/angular/46-simple-animations/ icon: rocket - text: Give a star link: https://github.com/tomalaforge/angular-challenges @@ -27,8 +27,8 @@ import MyIcon from '../../components/MyIcon.astro'; import SubscriptionForm from '../../components/SubscriptionForm.astro'; - - This repository gathers 45 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. + + This repository gathers 46 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. These challenges resolve around real-life issues or specific features to elevate your skills. diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx index f1c14ee87..1c6de9bab 100644 --- a/docs/src/content/docs/pt/index.mdx +++ b/docs/src/content/docs/pt/index.mdx @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositório possui 45 Desafios relacionados a Angular, Nx, RxJS, + + Este repositório possui 46 Desafios relacionados a Angular, Nx, RxJS, Ngrx e Typescript. Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de melhorar suas habilidades. diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx index 3e25ab430..77b9f61a3 100644 --- a/docs/src/content/docs/ru/index.mdx +++ b/docs/src/content/docs/ru/index.mdx @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Этот репозиторий содержит 45 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. + + Этот репозиторий содержит 46 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас. From dd83196c5780f9a41c019b87c30d930ac1efc495 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 08:26:45 +0100 Subject: [PATCH 044/361] docs(animations): add hint for related challenges --- docs/src/content/docs/challenges/angular/44-view-transition.md | 2 ++ .../src/content/docs/challenges/angular/46-simple-animations.md | 2 ++ .../content/docs/pt/challenges/angular/44-view-transition.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/docs/src/content/docs/challenges/angular/44-view-transition.md b/docs/src/content/docs/challenges/angular/44-view-transition.md index 6dbf21131..c9550f6e9 100644 --- a/docs/src/content/docs/challenges/angular/44-view-transition.md +++ b/docs/src/content/docs/challenges/angular/44-view-transition.md @@ -10,6 +10,8 @@ sidebar: ## Information +This is the second of two animation challenges, the goal of this series is to master animations in Angular. + The View Transition API is a brand new API that provides a set of features that allow developers to control and manipulate the transitions and animations between views within an application. It plays a pivotal role in enhancing the user experience (UX), bringing applications to life with engaging and captivating transitions to guide users through different pages or sections of the app. diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 29edaafb4..727ed63d3 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -11,6 +11,8 @@ sidebar: ## Information +This is the first of two animation challenges, the goal of this series is to master animations in Angular. + Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. Animations can improve your application and user experience in a number of ways: - Without animations, web page transitions can seem abrupt and jarring. diff --git a/docs/src/content/docs/pt/challenges/angular/44-view-transition.md b/docs/src/content/docs/pt/challenges/angular/44-view-transition.md index ead29d495..0d7e984bd 100644 --- a/docs/src/content/docs/pt/challenges/angular/44-view-transition.md +++ b/docs/src/content/docs/pt/challenges/angular/44-view-transition.md @@ -10,6 +10,8 @@ sidebar: ## Informação +Este é o segundo de três desafios animation, sendo o objetivo dominar animations em Angular. + A View Transition API é uma nova API que fornece um conjunto de funcionalidades, permitindo desenvolvedores controlarem e manipularem as transições e animações entre views dentro de uma aplicação. Isso tem um papel importante na melhoria da experiência do usuário (UX), trazendo vida a aplicações com transições atraentes e cativantes afim de guiar usuários por diferentes páginas e seções da aplicação. From 97ec15697346fb922e409090dde9ab80397adbce Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 09:02:46 +0100 Subject: [PATCH 045/361] fix: added missing author for new challenge --- docs/src/content/authors/sven-brodny.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/src/content/authors/sven-brodny.json diff --git a/docs/src/content/authors/sven-brodny.json b/docs/src/content/authors/sven-brodny.json new file mode 100644 index 000000000..3372743d8 --- /dev/null +++ b/docs/src/content/authors/sven-brodny.json @@ -0,0 +1,5 @@ +{ + "name": "Sven Brodny", + "linkedin": "https://www.linkedin.com/in/sven-brodny-0ba603237/", + "github": "https://github.com/svenson95" +} From 4a2080e07957634b500a98915ce2d04fd61f7500 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Tue, 20 Feb 2024 08:58:13 -0300 Subject: [PATCH 046/361] docs(pt): translate challenge 30 --- .../angular/30-interop-rxjs-signal.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/src/content/docs/pt/challenges/angular/30-interop-rxjs-signal.md diff --git a/docs/src/content/docs/pt/challenges/angular/30-interop-rxjs-signal.md b/docs/src/content/docs/pt/challenges/angular/30-interop-rxjs-signal.md new file mode 100644 index 000000000..acb3e4bc7 --- /dev/null +++ b/docs/src/content/docs/pt/challenges/angular/30-interop-rxjs-signal.md @@ -0,0 +1,19 @@ +--- +title: 🔴 Interoperabilidade Rxjs/Signal +description: Desafio 30 é sobre aprender como misturar signal com Rxjs +author: thomas-laforge +challengeNumber: 30 +command: angular-interop-rxjs-signal +sidebar: + order: 204 +--- + +## Informação + +Neste desafio, temos uma pequena aplicação reativa que usa **RxJs** e **NgRx/Component-Store**. + +O objetivo deste desafio é usar a nova **API Signal** introduzida no Angular v16. No entanto, não devemos converter tudo. Certas parte do código são mais adequadas com RxJS do que Signal. É sua decisão determinar o limite e observar como **Signal e RXJS coexistem**, além de como a interoperabilidade é feita no Angular. + +## Nota + +- Você pode usar qualquer biblioteca de terceiros se quiser, como **ngrx/signal-store**, **tanstack-query** ou **rxAngular**. From 25864887954cffcccc7340010b62dc79474f1fa9 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 17:57:04 +0100 Subject: [PATCH 047/361] docs(simple-animations): fix typo --- .../src/content/docs/challenges/angular/46-simple-animations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 727ed63d3..862085b73 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -19,7 +19,7 @@ Well-designed animations can make your application more fun and straightforward - Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions. - Good animations intuitively call the user's attention to where it is needed. -I would recommend you to read the [official documentation](https://angular.io/guide/animations). You will learn everything that is necessary to successfully complete the challenge. +I would recommend you read the [official documentation](https://angular.io/guide/animations). You will learn everything that is necessary to successfully complete the challenge. Otherwise look at this [working example](https://svenson95.github.io/ng-xmp-animations/) and [git repo](https://github.com/svenson95/ng-xmp-animations) to get inspired. From 31cfff9b3be65c00f767657126c1dc7dcbf5f24f Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 20 Feb 2024 18:12:55 +0100 Subject: [PATCH 048/361] style: red button unintended font-color black --- docs/src/components/ActionButtonFooter.astro | 4 +--- docs/src/components/SubscriptionForm.astro | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/src/components/ActionButtonFooter.astro b/docs/src/components/ActionButtonFooter.astro index 512532ffe..76213a3a5 100644 --- a/docs/src/components/ActionButtonFooter.astro +++ b/docs/src/components/ActionButtonFooter.astro @@ -51,8 +51,6 @@ const { data } = await getEntry('i18n', lang); .button-sponsor { background-color: red; border-color: red; - color: white; + color: white !important; } - - diff --git a/docs/src/components/SubscriptionForm.astro b/docs/src/components/SubscriptionForm.astro index b1aab50da..1d88c2b92 100644 --- a/docs/src/components/SubscriptionForm.astro +++ b/docs/src/components/SubscriptionForm.astro @@ -80,7 +80,7 @@ const { data } = await getEntry('i18n', lang ?? 'en'); align-items: center; border-radius: 999rem; padding: 0.5rem 1.125rem; - color: var(--sl-color-white); + color: var(--color-btn); line-height: 1.1875; text-decoration: none; font-size: var(--sl-text-sm); From 595c6f39a7351858e6b3cbb96d5cebda252aa919 Mon Sep 17 00:00:00 2001 From: Stanislav Gavrilov Date: Tue, 20 Feb 2024 21:24:21 +0300 Subject: [PATCH 049/361] docs(ru): 40-christmas-web-worker.md translation --- .../performance/40-christmas-web-worker.md | 33 +++++++++++++++++++ docs/src/content/i18n/ru.json | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 docs/src/content/docs/ru/challenges/performance/40-christmas-web-worker.md diff --git a/docs/src/content/docs/ru/challenges/performance/40-christmas-web-worker.md b/docs/src/content/docs/ru/challenges/performance/40-christmas-web-worker.md new file mode 100644 index 000000000..674ceed2b --- /dev/null +++ b/docs/src/content/docs/ru/challenges/performance/40-christmas-web-worker.md @@ -0,0 +1,33 @@ +--- +title: 🟠 Веб-воркеры +description: Испытание 40 о том как создать и использовать веб-воркер +author: thomas-laforge +challengeNumber: 40 +command: performance-christmas-web-worker +sidebar: + order: 119 +--- + +## Информация + +Это испытание было создано для [Angular Advent Calendar](https://angularchristmascalendar.com) 2023. + +Это простое приложение, где нужно нажать на кнопку **Discover**, чтобы увидеть сюрприз, скрывающийся за черным экраном. Тем не менее, взаимодействие с приложением оставляет желать лучшего. При нажатии на кнопку происходит зависание страницы, а затем, после краткой задержки, секрет раскрывается мгновенно и без какой-либо плавности в анимации. + +> Пояснение: Для того, чтобы вызвать зависание приложения, загрузчик использует функцию, выполняющую очень сложные вычисления. Хотя возможно было бы использовать обычный таймер, но это не суть данного испытания. + +Так как JavaScript работает в однопоточном режиме, выполнение ресурсоемких задач препятствует обновлению пользовательского интерфейса браузера и реагированию на клики мыши или другие действия. Задача этого испытания - разгрузить основной поток, перенеся сложные вычисления в отдельный поток. Для этой цели мы будем использовать веб-воркеры. Веб-воркеры способны запускать скрипты в фоне, не влияя на основной поток, что позволяет браузеру сохранять высокое качество пользовательского взаимодействия. + +В Angular использование этой технологии не так распространено, но внедрить её довольно легко. Есть схематик, который вы можете найти [здесь](https://angular.io/guide/web-worker) чтобы начать. + +## Пояснение + +Это испытание направлено на создание плавной анимации за счет перемещения функции, выполняющей сложные вычисления, в веб-воркер. + +Для начала, используя схематик, создайте веб-воркер и перенесите в него функцию, вызывающую проблемы. После этих шагов анимация должна стать плавной, а отображение процента выполнения — обновляться, тем самым значительно улучшив пользовательский опыт. + +:::note[Пояснение] +Поскольку мы находимся в рабочем пространстве Nx, просто замените команду `ng` на `nx` при запуске схематика. + +Если `nx` не установлен глобально на вашем компьютере, добавьте префикс `npx` к вашей команде. +::: diff --git a/docs/src/content/i18n/ru.json b/docs/src/content/i18n/ru.json index be1716a4c..4e58543ad 100644 --- a/docs/src/content/i18n/ru.json +++ b/docs/src/content/i18n/ru.json @@ -16,7 +16,7 @@ "challenge.footer.video": "Видео", "challenge.footer.gettingStarted.title": "Чтобы пройти это испытание, прочитайте:", "challenge.footer.gettingStarted.link": "Первые шаги", - "challenge.footer.upvoteAnswer": "Вы можете проголосовать за этот ответ 👍 если он вам понравился", + "challenge.footer.upvoteAnswer": "Вы можете проголосовать за ответ 👍 если он вам понравился", "subscription.button": "Подписаться", "subscription.email": "username@gmail.com", "subscription.note.title": "Примечание", From f40b9528acb79317a5cc0ca638d337b35986deae Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Wed, 21 Feb 2024 12:03:37 +0100 Subject: [PATCH 050/361] docs(simple-animations): improve statement & add stagger example video --- .../content/docs/challenges/angular/46-simple-animations.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 862085b73..44966aea4 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -25,7 +25,7 @@ Otherwise look at this [working example](https://svenson95.github.io/ng-xmp-anim ## Statement -The goal of this challenge is to add animations. +The goal of this challenge is to add animations, they should run when the user arrives on the page or reload the page. ## Constraints @@ -38,3 +38,6 @@ Add a fading or moving animation for the paragraphs on the left side. ### Level 2 Add a stagger animation for the list on the right side. + + From fe1609686f01d94963ff7e668c37cf36a05525cf Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Wed, 21 Feb 2024 12:45:13 +0100 Subject: [PATCH 051/361] docs(simple-animations): add constraint how to trigger animation --- .../content/docs/challenges/angular/46-simple-animations.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 44966aea4..03401c155 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -29,7 +29,8 @@ The goal of this challenge is to add animations, they should run when the user a ## Constraints -Don't use any CSS and utilize Angular's integrated `@angular/animations` API. +- Don't use any CSS and utilize Angular's integrated `@angular/animations` API. +- Don't trigger the animations with a button like in the examples, rather when the user enter or reload the page. ### Level 1 From ca0306dc53bf67a34c000396723d4cde92e9034d Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Wed, 21 Feb 2024 12:53:57 +0100 Subject: [PATCH 052/361] docs(simple-animations): add example video for fade and moving animation --- .../content/docs/challenges/angular/46-simple-animations.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 03401c155..f7c197a17 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -36,9 +36,13 @@ The goal of this challenge is to add animations, they should run when the user a Add a fading or moving animation for the paragraphs on the left side. + + ### Level 2 Add a stagger animation for the list on the right side. + From a41faf818b4056d817e0c99dfe3584d7a578f572 Mon Sep 17 00:00:00 2001 From: thomas Date: Thu, 22 Feb 2024 09:04:35 +0100 Subject: [PATCH 053/361] fix: test setup --- apps/angular/anchor-scrolling/jest.config.ts | 2 +- apps/angular/bug-cd/jest.config.ts | 2 +- apps/angular/crud/jest.config.ts | 2 +- apps/angular/injection-token/jest.config.ts | 2 +- apps/angular/interop-rxjs-signal/jest.config.ts | 2 +- apps/angular/projection/jest.config.ts | 2 +- apps/forms/control-value-accessor/jest.config.ts | 2 +- apps/ngrx/effect-selector/jest.config.ts | 2 +- apps/performance/ngfor-optimize/jest.config.ts | 2 +- apps/performance/scroll-cd/jest.config.ts | 2 +- apps/rxjs/catch-error/jest.config.ts | 2 +- apps/rxjs/race-condition/jest.config.ts | 2 +- apps/testing/checkbox/jest.config.ts | 2 +- apps/testing/create-harness/jest.config.ts | 2 +- apps/testing/harness/jest.config.ts | 2 +- apps/testing/input-output/jest.config.ts | 2 +- apps/testing/modal/jest.config.ts | 2 +- apps/testing/nested/jest.config.ts | 2 +- apps/testing/router-outlet/jest.config.ts | 2 +- apps/testing/table/jest.config.ts | 2 +- apps/testing/todos-list/jest.config.ts | 2 +- libs/angular/di/jest.config.ts | 2 +- libs/decoupling/brain/jest.config.ts | 2 +- libs/decoupling/core/jest.config.ts | 2 +- libs/decoupling/helmet/jest.config.ts | 2 +- libs/module-to-standalone/admin/feature/jest.config.ts | 2 +- libs/module-to-standalone/admin/shared/jest.config.ts | 2 +- libs/module-to-standalone/core/providers/jest.config.ts | 2 +- libs/module-to-standalone/core/service/jest.config.ts | 2 +- libs/module-to-standalone/forbidden/jest.config.ts | 2 +- libs/module-to-standalone/home/jest.config.ts | 2 +- libs/module-to-standalone/shell/jest.config.ts | 2 +- libs/module-to-standalone/user/contact/jest.config.ts | 2 +- libs/module-to-standalone/user/home/jest.config.ts | 2 +- libs/module-to-standalone/user/shell/jest.config.ts | 2 +- libs/ngrx-notification/backend/jest.config.ts | 2 +- libs/ngrx-notification/model/jest.config.ts | 2 +- libs/shared/directives/jest.config.ts | 2 +- libs/shared/ngrx-callstate-store/jest.config.ts | 2 +- libs/shared/utils/jest.config.ts | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) diff --git a/apps/angular/anchor-scrolling/jest.config.ts b/apps/angular/anchor-scrolling/jest.config.ts index 166572856..6915111a0 100644 --- a/apps/angular/anchor-scrolling/jest.config.ts +++ b/apps/angular/anchor-scrolling/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-anchor-scrolling', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/angular/anchor-scrolling', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/angular/bug-cd/jest.config.ts b/apps/angular/bug-cd/jest.config.ts index ded316d4c..1f24a7ce5 100644 --- a/apps/angular/bug-cd/jest.config.ts +++ b/apps/angular/bug-cd/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-bug-cd', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/angular/bug-cd', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/angular/crud/jest.config.ts b/apps/angular/crud/jest.config.ts index 485099109..74a17f135 100644 --- a/apps/angular/crud/jest.config.ts +++ b/apps/angular/crud/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-crud', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/apps/angular/crud', transform: { diff --git a/apps/angular/injection-token/jest.config.ts b/apps/angular/injection-token/jest.config.ts index c48bb4949..d7105f89b 100644 --- a/apps/angular/injection-token/jest.config.ts +++ b/apps/angular/injection-token/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-injection-token', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/angular/injection-token', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/angular/interop-rxjs-signal/jest.config.ts b/apps/angular/interop-rxjs-signal/jest.config.ts index 53f7481c3..23956ebcc 100644 --- a/apps/angular/interop-rxjs-signal/jest.config.ts +++ b/apps/angular/interop-rxjs-signal/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-interop-rxjs-signal', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/angular/interop-rxjs-signal', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/angular/projection/jest.config.ts b/apps/angular/projection/jest.config.ts index 2af97a39a..289a9b0e3 100644 --- a/apps/angular/projection/jest.config.ts +++ b/apps/angular/projection/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular-projection', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/apps/angular/projection', transform: { diff --git a/apps/forms/control-value-accessor/jest.config.ts b/apps/forms/control-value-accessor/jest.config.ts index a52c89870..4af08e195 100644 --- a/apps/forms/control-value-accessor/jest.config.ts +++ b/apps/forms/control-value-accessor/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'forms-control-value-accessor', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/forms/control-value-accessor', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/ngrx/effect-selector/jest.config.ts b/apps/ngrx/effect-selector/jest.config.ts index 7e97f0ba2..86ed38d00 100644 --- a/apps/ngrx/effect-selector/jest.config.ts +++ b/apps/ngrx/effect-selector/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'ngrx-effect-selector', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/apps/ngrx/effect-selector', transform: { diff --git a/apps/performance/ngfor-optimize/jest.config.ts b/apps/performance/ngfor-optimize/jest.config.ts index 49ac9d7ac..5b2ccaee0 100644 --- a/apps/performance/ngfor-optimize/jest.config.ts +++ b/apps/performance/ngfor-optimize/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'performance-ngfor-optimize', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/performance/ngfor-optimize', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/performance/scroll-cd/jest.config.ts b/apps/performance/scroll-cd/jest.config.ts index 7e8ea5b99..4c9105010 100644 --- a/apps/performance/scroll-cd/jest.config.ts +++ b/apps/performance/scroll-cd/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'performance-scroll-cd', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/apps/performance/scroll-cd', transform: { diff --git a/apps/rxjs/catch-error/jest.config.ts b/apps/rxjs/catch-error/jest.config.ts index be57e8c7b..f82342048 100644 --- a/apps/rxjs/catch-error/jest.config.ts +++ b/apps/rxjs/catch-error/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'rxjs-catch-error', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/rxjs/catch-error', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/rxjs/race-condition/jest.config.ts b/apps/rxjs/race-condition/jest.config.ts index b77456835..2e2e8920b 100644 --- a/apps/rxjs/race-condition/jest.config.ts +++ b/apps/rxjs/race-condition/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'rxjs-race-condition', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/apps/rxjs/race-condition', transform: { diff --git a/apps/testing/checkbox/jest.config.ts b/apps/testing/checkbox/jest.config.ts index ea6f808cf..0c5902908 100644 --- a/apps/testing/checkbox/jest.config.ts +++ b/apps/testing/checkbox/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-checkbox', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/apps/testing/checkbox', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/testing/create-harness/jest.config.ts b/apps/testing/create-harness/jest.config.ts index 195dab15a..1178b8aaf 100644 --- a/apps/testing/create-harness/jest.config.ts +++ b/apps/testing/create-harness/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-create-harness', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/harness/jest.config.ts b/apps/testing/harness/jest.config.ts index e342863b1..2b9e6d44c 100644 --- a/apps/testing/harness/jest.config.ts +++ b/apps/testing/harness/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-harness', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/input-output/jest.config.ts b/apps/testing/input-output/jest.config.ts index 7d2312104..63370e2a3 100644 --- a/apps/testing/input-output/jest.config.ts +++ b/apps/testing/input-output/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-input-output', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/modal/jest.config.ts b/apps/testing/modal/jest.config.ts index 137c0c8c7..809080bcc 100644 --- a/apps/testing/modal/jest.config.ts +++ b/apps/testing/modal/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-modal', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/nested/jest.config.ts b/apps/testing/nested/jest.config.ts index b6643db38..a89947bd9 100644 --- a/apps/testing/nested/jest.config.ts +++ b/apps/testing/nested/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-nested', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/router-outlet/jest.config.ts b/apps/testing/router-outlet/jest.config.ts index f8f0ad165..0bca8aebb 100644 --- a/apps/testing/router-outlet/jest.config.ts +++ b/apps/testing/router-outlet/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-router-outlet', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/apps/testing/table/jest.config.ts b/apps/testing/table/jest.config.ts index 98474ecca..56b0e7df7 100644 --- a/apps/testing/table/jest.config.ts +++ b/apps/testing/table/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-table', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/apps/testing/todos-list/jest.config.ts b/apps/testing/todos-list/jest.config.ts index 3b92b5677..eb61074e5 100644 --- a/apps/testing/todos-list/jest.config.ts +++ b/apps/testing/todos-list/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'testing-todos-list', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/libs/angular/di/jest.config.ts b/libs/angular/di/jest.config.ts index 3ac52266b..79303be1b 100644 --- a/libs/angular/di/jest.config.ts +++ b/libs/angular/di/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'angular/di', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/angular/di', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/decoupling/brain/jest.config.ts b/libs/decoupling/brain/jest.config.ts index 4e97ee0c0..443cc73ba 100644 --- a/libs/decoupling/brain/jest.config.ts +++ b/libs/decoupling/brain/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'decoupling-brain', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/decoupling/brain', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/decoupling/core/jest.config.ts b/libs/decoupling/core/jest.config.ts index 332658d30..f755dfa37 100644 --- a/libs/decoupling/core/jest.config.ts +++ b/libs/decoupling/core/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'decoupling-core', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/decoupling/core', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/decoupling/helmet/jest.config.ts b/libs/decoupling/helmet/jest.config.ts index 1adcccef8..961b9e926 100644 --- a/libs/decoupling/helmet/jest.config.ts +++ b/libs/decoupling/helmet/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'decoupling-helmet', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/decoupling/helmet', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/module-to-standalone/admin/feature/jest.config.ts b/libs/module-to-standalone/admin/feature/jest.config.ts index 4b02a6adb..547252ec2 100644 --- a/libs/module-to-standalone/admin/feature/jest.config.ts +++ b/libs/module-to-standalone/admin/feature/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-admin-feature', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/admin/feature', transform: { diff --git a/libs/module-to-standalone/admin/shared/jest.config.ts b/libs/module-to-standalone/admin/shared/jest.config.ts index 7ecd6da4b..41e66914b 100644 --- a/libs/module-to-standalone/admin/shared/jest.config.ts +++ b/libs/module-to-standalone/admin/shared/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-admin-shared', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/admin/shared', transform: { diff --git a/libs/module-to-standalone/core/providers/jest.config.ts b/libs/module-to-standalone/core/providers/jest.config.ts index f3c281d42..d7c348641 100644 --- a/libs/module-to-standalone/core/providers/jest.config.ts +++ b/libs/module-to-standalone/core/providers/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-core-providers', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/core/providers', transform: { diff --git a/libs/module-to-standalone/core/service/jest.config.ts b/libs/module-to-standalone/core/service/jest.config.ts index 8738d5428..82808fc64 100644 --- a/libs/module-to-standalone/core/service/jest.config.ts +++ b/libs/module-to-standalone/core/service/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-core-service', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/core/service', transform: { diff --git a/libs/module-to-standalone/forbidden/jest.config.ts b/libs/module-to-standalone/forbidden/jest.config.ts index 957e0a91a..747043666 100644 --- a/libs/module-to-standalone/forbidden/jest.config.ts +++ b/libs/module-to-standalone/forbidden/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-forbidden', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/module-to-standalone/forbidden', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/module-to-standalone/home/jest.config.ts b/libs/module-to-standalone/home/jest.config.ts index e5d36e59d..b4d6a048c 100644 --- a/libs/module-to-standalone/home/jest.config.ts +++ b/libs/module-to-standalone/home/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-home', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/module-to-standalone/home', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/module-to-standalone/shell/jest.config.ts b/libs/module-to-standalone/shell/jest.config.ts index 700343e31..ff53f23f6 100644 --- a/libs/module-to-standalone/shell/jest.config.ts +++ b/libs/module-to-standalone/shell/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-shell', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/module-to-standalone/shell', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/module-to-standalone/user/contact/jest.config.ts b/libs/module-to-standalone/user/contact/jest.config.ts index e0cdc798c..c6402b94a 100644 --- a/libs/module-to-standalone/user/contact/jest.config.ts +++ b/libs/module-to-standalone/user/contact/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-user-contact', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/user/contact', transform: { diff --git a/libs/module-to-standalone/user/home/jest.config.ts b/libs/module-to-standalone/user/home/jest.config.ts index e7f5f1fa3..90ae70418 100644 --- a/libs/module-to-standalone/user/home/jest.config.ts +++ b/libs/module-to-standalone/user/home/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-user-home', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/user/home', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/module-to-standalone/user/shell/jest.config.ts b/libs/module-to-standalone/user/shell/jest.config.ts index e7cae439d..74a019ba0 100644 --- a/libs/module-to-standalone/user/shell/jest.config.ts +++ b/libs/module-to-standalone/user/shell/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'module-to-standalone-user-shell', preset: '../../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../../coverage/libs/module-to-standalone/user/shell', transform: { diff --git a/libs/ngrx-notification/backend/jest.config.ts b/libs/ngrx-notification/backend/jest.config.ts index ff7b20c03..5152a2f1c 100644 --- a/libs/ngrx-notification/backend/jest.config.ts +++ b/libs/ngrx-notification/backend/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'ngrx-notification-backend', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/libs/ngrx-notification/backend', transform: { diff --git a/libs/ngrx-notification/model/jest.config.ts b/libs/ngrx-notification/model/jest.config.ts index 797a2214a..f9083fa9c 100644 --- a/libs/ngrx-notification/model/jest.config.ts +++ b/libs/ngrx-notification/model/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'ngrx-notification-model', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/libs/ngrx-notification/model', transform: { diff --git a/libs/shared/directives/jest.config.ts b/libs/shared/directives/jest.config.ts index b0dbb3590..3d1f082c1 100644 --- a/libs/shared/directives/jest.config.ts +++ b/libs/shared/directives/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'shared-directives', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../../coverage/libs/shared/directives', transform: { '^.+\\.(ts|mjs|js|html)$': [ diff --git a/libs/shared/ngrx-callstate-store/jest.config.ts b/libs/shared/ngrx-callstate-store/jest.config.ts index bd9423668..6c6eb9217 100644 --- a/libs/shared/ngrx-callstate-store/jest.config.ts +++ b/libs/shared/ngrx-callstate-store/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'shared-ngrx-callstate-store', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/libs/shared/ngrx-callstate-store', transform: { diff --git a/libs/shared/utils/jest.config.ts b/libs/shared/utils/jest.config.ts index e708878c4..278c93ab8 100644 --- a/libs/shared/utils/jest.config.ts +++ b/libs/shared/utils/jest.config.ts @@ -2,7 +2,7 @@ export default { displayName: 'shared-utils', preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/subscription-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], globals: {}, coverageDirectory: '../../../coverage/libs/shared/utils', transform: { From ed865c33cd40f9edcc0c8f424dd082bfbd2d5dec Mon Sep 17 00:00:00 2001 From: Stanislav Date: Sat, 24 Feb 2024 17:58:56 +0300 Subject: [PATCH 054/361] docs(ru): 43-signal-input translation --- .../ru/challenges/angular/43-signal-input.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs/src/content/docs/ru/challenges/angular/43-signal-input.md diff --git a/docs/src/content/docs/ru/challenges/angular/43-signal-input.md b/docs/src/content/docs/ru/challenges/angular/43-signal-input.md new file mode 100644 index 000000000..36c86bc63 --- /dev/null +++ b/docs/src/content/docs/ru/challenges/angular/43-signal-input.md @@ -0,0 +1,53 @@ +--- +title: 🟢 Signal Input +description: Испытание 43 про то как использовать signal inputs +author: thomas-laforge +challengeNumber: 43 +command: angular-signal-input +sidebar: + order: 16 +--- + +## Информация + +Наконец настал тот день, когда разработчики Angular добавили долгожданный реактивный input. +Фича, которую ждали на протяжении многих лет, появилась в версии 17.1 под названием `SignalInput`. +Теперь, вместо привычного декоратора `@Input`, у нас есть функция, которая возвращает сигнал. + +```ts +// старый способ +@Input() age?: number; + +// новый способ +age = input() +``` + +Если нужны обязательные inputs. + +```ts +// старый способ +@Input({required: true}) age!: number; + +// новый способ +age = input.required() +``` + +Если было нужно получить сигнал из input приходилось использовать сеттер. + +```ts +// старый способ +age = signal(0) +@Input({alias: 'age'}) set _age(age: number){ + this.age.set(age) +}; + +// новый способ +age = input() +``` + +## Пояснение + +Задача этого упражнения - переработать `UserComponent`, чтобы в нем был использован `SignalInput`. + +- У вас есть обязательные и не обязательные inputs. +- Вы можете использовать функцию `transform` для ввода `age`, чтобы преобразовать свойство в число. From 1b10faff5ee8413a3ecf689b863aced52e54d529 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Sun, 25 Feb 2024 15:49:13 +0100 Subject: [PATCH 055/361] docs(permissions): update article content --- .../docs/challenges/angular/6-permissions.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/6-permissions.md b/docs/src/content/docs/challenges/angular/6-permissions.md index 66ada3acb..eaa4d7a2b 100644 --- a/docs/src/content/docs/challenges/angular/6-permissions.md +++ b/docs/src/content/docs/challenges/angular/6-permissions.md @@ -11,13 +11,16 @@ sidebar: ## Information -Structural directive is an important concept you will need to master to improve your angular skills and knowledge. This will be the first part of this challenge. +Structural directives are directives which change the DOM layout by adding and removing DOM elements. This is an important concept you'll need to improve your angular skills and knowledge. This will be the first part of this challenge. For more information check out the [official documentation](https://angular.io/guide/structural-directives). -Guard is also very important since you will always need it in every application you build. +Guards like `CanActivate` or `CanMatch` are also very important, since you'll need it in the most application's you build. If you're not very familiar with route guards, check out this two articles. + +- [Everything you need to know about route Guard in Angular](https://itnext.io/everything-you-need-to-know-about-route-guard-in-angular-697a062d3198) +- [Create a route Guard to manage permissions](https://medium.com/@thomas.laforge/create-a-route-guard-to-manage-permissions-26f16cc9a1ca) ## Statement -In LoginComponent, you will find 6 buttons corresponding to 6 differents user's role. +In `LoginComponent` you'll find 6 buttons corresponding to 6 different user's role. - Admin - Manager @@ -29,12 +32,12 @@ In LoginComponent, you will find 6 buttons corresponding to 6 differents user's ## Step 1 -In `InformationComponent`, you need to display the correct piece of information for each role using a structural directive. +In `InformationComponent` you'll need to display the correct piece of information for each role using a structural directive. ### Constraints -- no `ngIf` or `@if` inside `InformationComponent` -- importing the store inside `InformationComponent` is not allowed. +- No `ngIf` or `@if` inside `InformationComponent`. +- Importing the store inside `InformationComponent` is not allowed. You should end up with something like below: @@ -52,4 +55,4 @@ You should end up with something like below: ## Step 2 -In `Routes.ts`, you should route all users to the correct `DashboardComponent` using `CanMatch` guard. +In `Routes.ts` you should route all users to the correct `DashboardComponent` using `CanMatch` guard. From 7a8aab424a7e9a021cfca76b248e051fd8328e3d Mon Sep 17 00:00:00 2001 From: thomas Date: Mon, 26 Feb 2024 10:44:52 +0100 Subject: [PATCH 056/361] fix: badge new --- 45-react-in-angular.md | 3 +-- .../src/content/docs/challenges/angular/45-react-in-angular.md | 1 - .../content/docs/es/challenges/angular/39-injection-token.md | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/45-react-in-angular.md b/45-react-in-angular.md index 4a07c9691..b8bc73b68 100644 --- a/45-react-in-angular.md +++ b/45-react-in-angular.md @@ -6,7 +6,6 @@ challengeNumber: 45 command: angular-react-in-angular sidebar: order: 209 - badge: New --- O objetivo deste desafio é usar um componente React dentro de uma aplicação Angular. @@ -15,7 +14,7 @@ Muitos componentes estão disponíveis em React, e pode ser interessante usar el ## Informação -Neste desafio temos uma simples aplicação e um componente React `ReactPost` em `app/react` para ilustrar um componente React de uma biblioteca. +Neste desafio temos uma simples aplicação e um componente React `ReactPost` em `app/react` para ilustrar um componente React de uma biblioteca. ## Declaração diff --git a/docs/src/content/docs/challenges/angular/45-react-in-angular.md b/docs/src/content/docs/challenges/angular/45-react-in-angular.md index 3c56d88f1..f2f83cd86 100644 --- a/docs/src/content/docs/challenges/angular/45-react-in-angular.md +++ b/docs/src/content/docs/challenges/angular/45-react-in-angular.md @@ -6,7 +6,6 @@ challengeNumber: 45 command: angular-react-in-angular sidebar: order: 209 - badge: New --- The goal of this challenge is to use a React component inside an Angular application. diff --git a/docs/src/content/docs/es/challenges/angular/39-injection-token.md b/docs/src/content/docs/es/challenges/angular/39-injection-token.md index 01eeb8d5c..3504341d7 100644 --- a/docs/src/content/docs/es/challenges/angular/39-injection-token.md +++ b/docs/src/content/docs/es/challenges/angular/39-injection-token.md @@ -6,7 +6,6 @@ challengeNumber: 39 command: angular-injection-token sidebar: order: 118 - badge: New --- ## Información From df93f31226ef24a3716a1a586c65a1747b8aa004 Mon Sep 17 00:00:00 2001 From: thomas Date: Mon, 26 Feb 2024 10:47:45 +0100 Subject: [PATCH 057/361] feat: add sven for challenge contribution --- .all-contributorsrc | 21 +++++++++++---------- README.md | 6 +++--- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5e94f8a01..6a919da8f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -88,6 +88,16 @@ "challenge" ] }, + { + "login": "svenson95", + "name": "Sven Brodny", + "avatar_url": "https://avatars.githubusercontent.com/u/46655156?v=4", + "profile": "https://svenson95.github.io/sb-portfolio/", + "contributions": [ + "doc", + "challenge" + ] + }, { "login": "alan-bio", "name": "Alan Dragicevich", @@ -210,18 +220,9 @@ "contributions": [ "doc" ] - }, - { - "login": "svenson95", - "name": "Sven Brodny", - "avatar_url": "https://avatars.githubusercontent.com/u/46655156?v=4", - "profile": "https://svenson95.github.io/sb-portfolio/", - "contributions": [ - "doc" - ] } ], "contributorsPerLine": 7, "linkToUsage": true, "commitType": "docs" -} +} \ No newline at end of file diff --git a/README.md b/README.md index 8d4d9a069..8cafa9b9d 100644 --- a/README.md +++ b/README.md @@ -39,24 +39,24 @@ Check [all 46 challenges](https://angular-challenges.vercel.app/) Devesh Chaudhari
Devesh Chaudhari

💻 🐛 🧩 stillst
stillst

🧩 🇷🇺 Wandrille
Wandrille

🧩 + Sven Brodny
Sven Brodny

📖 🧩 Alan Dragicevich
Alan Dragicevich

📖 - Michel EDIGHOFFER
Michel EDIGHOFFER

📖 + Michel EDIGHOFFER
Michel EDIGHOFFER

📖 Gerardo Sebastian Gonzalez
Gerardo Sebastian Gonzalez

📖 Evseev Yuriy
Evseev Yuriy

🐛 Tomer953
Tomer953

🐛 📖 💻 Dmitriy Mishchenko
Dmitriy Mishchenko

📖 Sagar Devkota
Sagar Devkota

📖 💻 Nelson Gutierrez
Nelson Gutierrez

🇪🇸 - Hossain K. M.
Hossain K. M.

📖 + Hossain K. M.
Hossain K. M.

📖 Diogo Nishikawa
Diogo Nishikawa

💻 🇵🇹 📖 Erick Rodriguez
Erick Rodriguez

🇪🇸 Eduardo Roth
Eduardo Roth

📖 🇪🇸 Fernando Bello
Fernando Bello

📖 - Sven Brodny
Sven Brodny

📖 From 0bbaeeb405b7f6c7428421c49e48143bbb04e4bd Mon Sep 17 00:00:00 2001 From: thomas Date: Mon, 26 Feb 2024 10:49:39 +0100 Subject: [PATCH 058/361] feat: add note --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8cafa9b9d..7ccd5a1c1 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ Check [all 46 challenges](https://angular-challenges.vercel.app/) Contributions of any kind are welcome. +If I have forgotten to add you as a contributor, please reach out to me. 🙏 + ## Licensev MIT From 27e620fa8272c742055faeb590034044769f5c1f Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Thu, 29 Feb 2024 14:38:42 +0100 Subject: [PATCH 059/361] feat(challenge 47): typescript enums vs union types --- README.md | 2 +- .../enums-vs-union-types/.eslintrc.json | 36 ++++++++ .../typescript/enums-vs-union-types/README.md | 13 +++ .../enums-vs-union-types/project.json | 73 +++++++++++++++ .../src/app/app.component.ts | 83 ++++++++++++++++++ .../src/app/app.config.ts | 5 ++ .../enums-vs-union-types/src/assets/.gitkeep | 0 .../enums-vs-union-types/src/favicon.ico | Bin 0 -> 15086 bytes .../enums-vs-union-types/src/index.html | 13 +++ .../enums-vs-union-types/src/main.ts | 7 ++ .../enums-vs-union-types/src/styles.scss | 5 ++ .../enums-vs-union-types/tailwind.config.js | 14 +++ .../enums-vs-union-types/tsconfig.app.json | 10 +++ .../enums-vs-union-types/tsconfig.editor.json | 7 ++ .../enums-vs-union-types/tsconfig.json | 30 +++++++ challenge-number.json | 4 +- .../angular/46-simple-animations.md | 2 - .../typescript/47-enums-vs-union-types.md | 67 ++++++++++++++ docs/src/content/docs/es/index.mdx | 6 +- docs/src/content/docs/fr/index.mdx | 6 +- docs/src/content/docs/index.mdx | 4 +- docs/src/content/docs/pt/index.mdx | 6 +- docs/src/content/docs/ru/index.mdx | 6 +- 23 files changed, 380 insertions(+), 19 deletions(-) create mode 100644 apps/typescript/enums-vs-union-types/.eslintrc.json create mode 100644 apps/typescript/enums-vs-union-types/README.md create mode 100644 apps/typescript/enums-vs-union-types/project.json create mode 100644 apps/typescript/enums-vs-union-types/src/app/app.component.ts create mode 100644 apps/typescript/enums-vs-union-types/src/app/app.config.ts create mode 100644 apps/typescript/enums-vs-union-types/src/assets/.gitkeep create mode 100644 apps/typescript/enums-vs-union-types/src/favicon.ico create mode 100644 apps/typescript/enums-vs-union-types/src/index.html create mode 100644 apps/typescript/enums-vs-union-types/src/main.ts create mode 100644 apps/typescript/enums-vs-union-types/src/styles.scss create mode 100644 apps/typescript/enums-vs-union-types/tailwind.config.js create mode 100644 apps/typescript/enums-vs-union-types/tsconfig.app.json create mode 100644 apps/typescript/enums-vs-union-types/tsconfig.editor.json create mode 100644 apps/typescript/enums-vs-union-types/tsconfig.json create mode 100644 docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md diff --git a/README.md b/README.md index 7ccd5a1c1..09a91e682 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 46 challenges](https://angular-challenges.vercel.app/) +Check [all 47 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ diff --git a/apps/typescript/enums-vs-union-types/.eslintrc.json b/apps/typescript/enums-vs-union-types/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/typescript/enums-vs-union-types/README.md b/apps/typescript/enums-vs-union-types/README.md new file mode 100644 index 000000000..b23e10094 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/README.md @@ -0,0 +1,13 @@ +# Enums vs Union Types + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve typescript-enums-vs-union-types +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/typescript/47-enums-vs-union-types/). diff --git a/apps/typescript/enums-vs-union-types/project.json b/apps/typescript/enums-vs-union-types/project.json new file mode 100644 index 000000000..63e9a04c0 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/project.json @@ -0,0 +1,73 @@ +{ + "name": "typescript-enums-vs-union-types", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/typescript/enums-vs-union-types/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/typescript/enums-vs-union-types", + "index": "apps/typescript/enums-vs-union-types/src/index.html", + "browser": "apps/typescript/enums-vs-union-types/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/typescript/enums-vs-union-types/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/typescript/enums-vs-union-types/src/favicon.ico", + "apps/typescript/enums-vs-union-types/src/assets" + ], + "styles": ["apps/typescript/enums-vs-union-types/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "typescript-enums-vs-union-types:build:production" + }, + "development": { + "buildTarget": "typescript-enums-vs-union-types:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "typescript-enums-vs-union-types:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"] + } + } +} diff --git a/apps/typescript/enums-vs-union-types/src/app/app.component.ts b/apps/typescript/enums-vs-union-types/src/app/app.component.ts new file mode 100644 index 000000000..12fae6d88 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/src/app/app.component.ts @@ -0,0 +1,83 @@ +import { Component, computed, signal } from '@angular/core'; + +enum Difficulty { + EASY = 'easy', + NORMAL = 'normal', +} + +enum Direction { + LEFT = 'left', + RIGHT = 'right', +} + +@Component({ + standalone: true, + imports: [], + selector: 'app-root', + template: ` +
+
+ + +
+

Selected Difficulty: {{ difficultyLabel() }}

+
+ +
+
+ + +
+

{{ directionLabel() }}

+
+ `, + styles: ` + section { + @apply flex flex-col mx-auto my-5 w-fit gap-2 items-center; + + > div { + @apply flex w-fit gap-5; + } + } + + button { + @apply rounded-md border px-4 py-2; + } + `, +}) +export class AppComponent { + readonly Difficulty = Difficulty; + readonly difficulty = signal(Difficulty.EASY); + + readonly Direction = Direction; + readonly direction = signal(undefined); + + readonly difficultyLabel = computed(() => { + switch (this.difficulty()) { + case Difficulty.EASY: + return Difficulty.EASY; + case Difficulty.NORMAL: + return Difficulty.NORMAL; + } + }); + + readonly directionLabel = computed(() => { + const prefix = 'You choosed to go'; + switch (this.direction()) { + case Direction.LEFT: + return `${prefix} ${Direction.LEFT}`; + case Direction.RIGHT: + return `${prefix} ${Direction.RIGHT}`; + default: + return 'Choose a direction!'; + } + }); +} diff --git a/apps/typescript/enums-vs-union-types/src/app/app.config.ts b/apps/typescript/enums-vs-union-types/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/typescript/enums-vs-union-types/src/assets/.gitkeep b/apps/typescript/enums-vs-union-types/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/typescript/enums-vs-union-types/src/favicon.ico b/apps/typescript/enums-vs-union-types/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 zcmeI332;U^%p|z7g|#(P)qFEA@4f!_@qOK2 z_lJl}!lhL!VT_U|uN7%8B2iKH??xhDa;*`g{yjTFWHvXn;2s{4R7kH|pKGdy(7z!K zgftM+Ku7~24TLlh(!g)gz|foI94G^t2^IO$uvX$3(OR0<_5L2sB)lMAMy|+`xodJ{ z_Uh_1m)~h?a;2W{dmhM;u!YGo=)OdmId_B<%^V^{ovI@y`7^g1_V9G}*f# zNzAtvou}I!W1#{M^@ROc(BZ! z+F!!_aR&Px3_reO(EW+TwlW~tv*2zr?iP7(d~a~yA|@*a89IUke+c472NXM0wiX{- zl`UrZC^1XYyf%1u)-Y)jj9;MZ!SLfd2Hl?o|80Su%Z?To_=^g_Jt0oa#CT*tjx>BI z16wec&AOWNK<#i0Qd=1O$fymLRoUR*%;h@*@v7}wApDl^w*h}!sYq%kw+DKDY)@&A z@9$ULEB3qkR#85`lb8#WZw=@})#kQig9oqy^I$dj&k4jU&^2(M3q{n1AKeGUKPFbr z1^<)aH;VsG@J|B&l>UtU#Ejv3GIqERzYgL@UOAWtW<{p#zy`WyJgpCy8$c_e%wYJL zyGHRRx38)HyjU3y{-4z6)pzb>&Q1pR)B&u01F-|&Gx4EZWK$nkUkOI|(D4UHOXg_- zw{OBf!oWQUn)Pe(=f=nt=zkmdjpO^o8ZZ9o_|4tW1ni+Un9iCW47*-ut$KQOww!;u z`0q)$s6IZO!~9$e_P9X!hqLxu`fpcL|2f^I5d4*a@Dq28;@2271v_N+5HqYZ>x;&O z05*7JT)mUe&%S0@UD)@&8SmQrMtsDfZT;fkdA!r(S=}Oz>iP)w=W508=Rc#nNn7ym z1;42c|8($ALY8#a({%1#IXbWn9-Y|0eDY$_L&j{63?{?AH{);EzcqfydD$@-B`Y3<%IIj7S7rK_N}je^=dEk%JQ4c z!tBdTPE3Tse;oYF>cnrapWq*o)m47X1`~6@(!Y29#>-#8zm&LXrXa(3=7Z)ElaQqj z-#0JJy3Fi(C#Rx(`=VXtJ63E2_bZGCz+QRa{W0e2(m3sI?LOcUBx)~^YCqZ{XEPX)C>G>U4tfqeH8L(3|pQR*zbL1 zT9e~4Tb5p9_G}$y4t`i*4t_Mr9QYvL9C&Ah*}t`q*}S+VYh0M6GxTTSXI)hMpMpIq zD1ImYqJLzbj0}~EpE-aH#VCH_udYEW#`P2zYmi&xSPs_{n6tBj=MY|-XrA;SGA_>y zGtU$?HXm$gYj*!N)_nQ59%lQdXtQZS3*#PC-{iB_sm+ytD*7j`D*k(P&IH2GHT}Eh z5697eQECVIGQAUe#eU2I!yI&%0CP#>%6MWV z@zS!p@+Y1i1b^QuuEF*13CuB zu69dve5k7&Wgb+^s|UB08Dr3u`h@yM0NTj4h7MnHo-4@xmyr7(*4$rpPwsCDZ@2be zRz9V^GnV;;?^Lk%ynzq&K(Aix`mWmW`^152Hoy$CTYVehpD-S1-W^#k#{0^L`V6CN+E z!w+xte;2vu4AmVNEFUOBmrBL>6MK@!O2*N|2=d|Y;oN&A&qv=qKn73lDD zI(+oJAdgv>Yr}8(&@ZuAZE%XUXmX(U!N+Z_sjL<1vjy1R+1IeHt`79fnYdOL{$ci7 z%3f0A*;Zt@ED&Gjm|OFTYBDe%bbo*xXAQsFz+Q`fVBH!N2)kaxN8P$c>sp~QXnv>b zwq=W3&Mtmih7xkR$YA)1Yi?avHNR6C99!u6fh=cL|KQ&PwF!n@ud^n(HNIImHD!h87!i*t?G|p0o+eelJ?B@A64_9%SBhNaJ64EvKgD&%LjLCYnNfc; znj?%*p@*?dq#NqcQFmmX($wms@CSAr9#>hUR^=I+=0B)vvGX%T&#h$kmX*s=^M2E!@N9#m?LhMvz}YB+kd zG~mbP|D(;{s_#;hsKK9lbVK&Lo734x7SIFJ9V_}2$@q?zm^7?*XH94w5Qae{7zOMUF z^?%F%)c1Y)Q?Iy?I>knw*8gYW#ok|2gdS=YYZLiD=CW|Nj;n^x!=S#iJ#`~Ld79+xXpVmUK^B(xO_vO!btA9y7w3L3-0j-y4 z?M-V{%z;JI`bk7yFDcP}OcCd*{Q9S5$iGA7*E1@tfkyjAi!;wP^O71cZ^Ep)qrQ)N z#wqw0_HS;T7x3y|`P==i3hEwK%|>fZ)c&@kgKO1~5<5xBSk?iZV?KI6&i72H6S9A* z=U(*e)EqEs?Oc04)V-~K5AUmh|62H4*`UAtItO$O(q5?6jj+K^oD!04r=6#dsxp?~}{`?&sXn#q2 zGuY~7>O2=!u@@Kfu7q=W*4egu@qPMRM>(eyYyaIE<|j%d=iWNdGsx%c!902v#ngNg z@#U-O_4xN$s_9?(`{>{>7~-6FgWpBpqXb`Ydc3OFL#&I}Irse9F_8R@4zSS*Y*o*B zXL?6*Aw!AfkNCgcr#*yj&p3ZDe2y>v$>FUdKIy_2N~}6AbHc7gA3`6$g@1o|dE>vz z4pl(j9;kyMsjaw}lO?(?Xg%4k!5%^t#@5n=WVc&JRa+XT$~#@rldvN3S1rEpU$;XgxVny7mki3 z-Hh|jUCHrUXuLr!)`w>wgO0N%KTB-1di>cj(x3Bav`7v z3G7EIbU$z>`Nad7Rk_&OT-W{;qg)-GXV-aJT#(ozdmnA~Rq3GQ_3mby(>q6Ocb-RgTUhTN)))x>m&eD;$J5Bg zo&DhY36Yg=J=$Z>t}RJ>o|@hAcwWzN#r(WJ52^g$lh^!63@hh+dR$&_dEGu&^CR*< z!oFqSqO@>xZ*nC2oiOd0eS*F^IL~W-rsrO`J`ej{=ou_q^_(<$&-3f^J z&L^MSYWIe{&pYq&9eGaArA~*kA + + + + typescript-enums-vs-union-types + + + + + + + + diff --git a/apps/typescript/enums-vs-union-types/src/main.ts b/apps/typescript/enums-vs-union-types/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/typescript/enums-vs-union-types/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/typescript/enums-vs-union-types/src/styles.scss b/apps/typescript/enums-vs-union-types/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/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/typescript/enums-vs-union-types/tailwind.config.js b/apps/typescript/enums-vs-union-types/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/typescript/enums-vs-union-types/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/typescript/enums-vs-union-types/tsconfig.app.json b/apps/typescript/enums-vs-union-types/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/typescript/enums-vs-union-types/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/typescript/enums-vs-union-types/tsconfig.editor.json b/apps/typescript/enums-vs-union-types/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/typescript/enums-vs-union-types/tsconfig.json b/apps/typescript/enums-vs-union-types/tsconfig.json new file mode 100644 index 000000000..db0ec0f25 --- /dev/null +++ b/apps/typescript/enums-vs-union-types/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json", + }, + { + "path": "./tsconfig.editor.json", + }, + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true, + }, +} diff --git a/challenge-number.json b/challenge-number.json index bba17af31..fee6a9627 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,6 +1,6 @@ { - "total": 46, - "🟢": 17, + "total": 47, + "🟢": 18, "🟠": 120, "🔴": 209 } diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index f7c197a17..9a92e89ff 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -6,7 +6,6 @@ challengeNumber: 46 command: angular-simple-animations sidebar: order: 17 - badge: New --- ## Information @@ -45,4 +44,3 @@ Add a stagger animation for the list on the right side. - diff --git a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md new file mode 100644 index 000000000..c214be280 --- /dev/null +++ b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md @@ -0,0 +1,67 @@ +--- +title: 🟢 Enums vs Union Types +description: Challenge 47 is about the comparison between enums and union types +author: sven-brodny +challengeNumber: 47 +command: typescript-enums-vs-union-types +sidebar: + order: 18 + badge: New +--- + +## Information + +[Enums](https://www.typescriptlang.org/docs/handbook/enums.html) allow developers to define a set of named constants that represent a specific type. TypeScript provides both numeric and string-based enums. + +```typescript +enum Difficulty { + EASY = 'EASY', + NORMAL = 'NORMAL', +} +``` + +On the other hand, [Union Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) are simpler than enums, as they don't require any additional runtime or compilation overhead. + +```typescript +type Difficulty = 'EASY' | 'NORMAL'; +``` + +### Reasons to use Union types + +Enums are a conecpt borrowed from languages like C# and Java. TypeScript Enums are compiled into JavaScript objects with keys for both the names and values of the Enum members. This results in larger output files and additional memory consumption, which can be particularly problematic in performance-critical applications. + +Enums have some more pitfalls as well: + +- Non-const enums do not fit to the conect "a typed superset of JavaScript". They violate the concept by emitting JavaScript objects that live in runtime with a syntax that is not compatible with JavaScript. +- Const enums in contrast cannot be transpiled with Babel. But there are workarounds for this issue, e. g. using `babel-plugin-const-enum` plugin. +- To use enums you have to import them, if you want to use enum values in a template, you'll need to declare a variable in your component too. +- Numeric enums are not type safe ... + +```typescript +enum Difficulty { + EASY = 0, + NORMAL = 1, +} +const hard: Difficulty = 2; // no error +``` + +### Reasons to use Enums + +With an enum, it is much easier to find all usages of a value in a project, thus refactoring & maintaining is extremly easy. If you stick to assigning strings to the enum keys all the time, you can avoid a lot of issues. + +Another good thing is that they add meaning to otherwise meaningless values, so they can improve readability. For example `HttpStatus.Forbidden` gives more information than `Forbidden`. + +### Conclusion + +Enums are not redundant, but in most cases union is preferred. Unless you care a lot about maintainability, where Enums fit a little bit better. Here are some more interesing articles discussing this subject: + +- [Should You Use Enums or Union Types in Typescript?](https://www.bam.tech/article/should-you-use-enums-or-union-types-in-typescript) +- [Typescript has unions, so are enums redundant?](https://stackoverflow.com/questions/40275832/typescript-has-unions-so-are-enums-redundant) +- [Tidy TypeScript: Prefer union types over enums](https://fettblog.eu/tidy-typescript-avoid-enums/) + +## Statement + +The goal of this challenge is to refactor the enums `Difficulty` & `Direction` + +- Refactor `Difficulty` to const enum +- Refacotr `Direction` to union type diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx index deb834078..f6b752cfb 100644 --- a/docs/src/content/docs/es/index.mdx +++ b/docs/src/content/docs/es/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir al Desafío más reciente - link: /es/challenges/angular/46-simple-animations/ + link: /es/challenges/typescript/47-enums-vs-union-types/ icon: rocket - text: Dar una estrella link: https://github.com/tomalaforge/angular-challenges @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositorio contiene 46 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. + + Este repositorio contiene 47 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript. Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades. diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx index d24f92a88..ffd0c6ec9 100644 --- a/docs/src/content/docs/fr/index.mdx +++ b/docs/src/content/docs/fr/index.mdx @@ -15,7 +15,7 @@ hero: icon: right-arrow variant: primary - text: Aller au dernier Challenge - link: /fr/challenges/angular/46-simple-animations/ + link: /fr/challenges/typescript/47-enums-vs-union-types/ icon: rocket - text: Donne une étoile link: https://github.com/tomalaforge/angular-challenges @@ -28,8 +28,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Ce répertoire rassemble 46 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. + + Ce répertoire rassemble 47 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index a17253336..1e1d132c1 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -27,8 +27,8 @@ import MyIcon from '../../components/MyIcon.astro'; import SubscriptionForm from '../../components/SubscriptionForm.astro'; - - This repository gathers 46 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. + + This repository gathers 47 Challenges related to Angular, Nx, RxJS, Ngrx and Typescript. These challenges resolve around real-life issues or specific features to elevate your skills. diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx index 1c6de9bab..068c538a0 100644 --- a/docs/src/content/docs/pt/index.mdx +++ b/docs/src/content/docs/pt/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Ir para o desafio mais recente - link: /pt/challenges/angular/46-simple-animations/ + link: /pt/challenges/typescript/47-enums-vs-union-types/ icon: rocket - text: Dar uma estrela link: https://github.com/tomalaforge/angular-challenges @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Este repositório possui 46 Desafios relacionados a Angular, Nx, RxJS, + + Este repositório possui 47 Desafios relacionados a Angular, Nx, RxJS, Ngrx e Typescript. Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de melhorar suas habilidades. diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx index 77b9f61a3..35fe566c4 100644 --- a/docs/src/content/docs/ru/index.mdx +++ b/docs/src/content/docs/ru/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Перейти к последней задаче - link: /ru/challenges/angular/46-simple-animations/ + link: /ru/challenges/typescript/47-enums-vs-union-types/ icon: rocket - text: Добавить звезду link: https://github.com/tomalaforge/angular-challenges @@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro'; import SubscriptionForm from '../../../components/SubscriptionForm.astro'; - - Этот репозиторий содержит 46 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. + + Этот репозиторий содержит 47 Испытания, связанных с Angular, Nx, RxJS, Ngrx and Typescript. Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас. From 80c0b78f323bc9d1bea85bd79184e2060e96f2e6 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Thu, 29 Feb 2024 14:51:27 +0100 Subject: [PATCH 060/361] fix(challenge 47): typos --- .../typescript/47-enums-vs-union-types.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md index c214be280..bac9d2624 100644 --- a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md +++ b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md @@ -26,13 +26,13 @@ On the other hand, [Union Types](https://www.typescriptlang.org/docs/handbook/2/ type Difficulty = 'EASY' | 'NORMAL'; ``` -### Reasons to use Union types +### Reasons to use Union Types -Enums are a conecpt borrowed from languages like C# and Java. TypeScript Enums are compiled into JavaScript objects with keys for both the names and values of the Enum members. This results in larger output files and additional memory consumption, which can be particularly problematic in performance-critical applications. +Enums are a concept borrowed from languages like C# and Java. TypeScript Enums are compiled into JavaScript objects with keys for both the names and values of the Enum members. This results in larger output files and additional memory consumption, which can be particularly problematic in performance-critical applications. Enums have some more pitfalls as well: -- Non-const enums do not fit to the conect "a typed superset of JavaScript". They violate the concept by emitting JavaScript objects that live in runtime with a syntax that is not compatible with JavaScript. +- Non-const enums do not fit to the concept "a typed superset of JavaScript". They violate the concept by emitting JavaScript objects that live in runtime with a syntax that is not compatible with JavaScript. - Const enums in contrast cannot be transpiled with Babel. But there are workarounds for this issue, e. g. using `babel-plugin-const-enum` plugin. - To use enums you have to import them, if you want to use enum values in a template, you'll need to declare a variable in your component too. - Numeric enums are not type safe ... @@ -53,7 +53,7 @@ Another good thing is that they add meaning to otherwise meaningless values, so ### Conclusion -Enums are not redundant, but in most cases union is preferred. Unless you care a lot about maintainability, where Enums fit a little bit better. Here are some more interesing articles discussing this subject: +Enums are not redundant, but in most cases union types are preferred. Unless you care a lot about maintainability, where Enums maybe fit a little bit better. Here are some more interesing articles discussing this subject: - [Should You Use Enums or Union Types in Typescript?](https://www.bam.tech/article/should-you-use-enums-or-union-types-in-typescript) - [Typescript has unions, so are enums redundant?](https://stackoverflow.com/questions/40275832/typescript-has-unions-so-are-enums-redundant) @@ -61,7 +61,7 @@ Enums are not redundant, but in most cases union is preferred. Unless you care a ## Statement -The goal of this challenge is to refactor the enums `Difficulty` & `Direction` +The goal of this challenge is to refactor the enums `Difficulty` & `Direction`. -- Refactor `Difficulty` to const enum -- Refacotr `Direction` to union type +- Refactor `Difficulty` to const enum. +- Refactor `Direction` to union type. From 8ccb746c4c4de06d4b45665f32f0eb48aec80b8e Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Sun, 3 Mar 2024 16:33:24 +0100 Subject: [PATCH 061/361] docs(enums-vs-union-types): update docs content --- .../typescript/47-enums-vs-union-types.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md index bac9d2624..b918c391d 100644 --- a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md +++ b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md @@ -47,9 +47,19 @@ const hard: Difficulty = 2; // no error ### Reasons to use Enums -With an enum, it is much easier to find all usages of a value in a project, thus refactoring & maintaining is extremly easy. If you stick to assigning strings to the enum keys all the time, you can avoid a lot of issues. +Enums are the best option for code refactoring, it is much easier to find all usages of a value in a project, thus refactoring & maintaining is extremly easy. If you stick to assigning strings to the enum keys all the time, you can avoid a lot of issues. -Another good thing is that they add meaning to otherwise meaningless values, so they can improve readability. For example `HttpStatus.Forbidden` gives more information than `Forbidden`. +It's true that enums produces larger output files, but that's not always a real problem. As long as the enum do it's job without any problems, it shouldn't be something you care that much about. + +Another good thing is that the necessary enum prefix add meaning to otherwise meaningless values, so they can improve readability. For example `HttpStatus.Forbidden` gives more information than `Forbidden`. + +### Mapped types + +A [mapped type](https://learntypescript.dev/08/l2-mapped-type) is the process of creating a new type by mapping type information from an existing type. + +```typescript +type Difficulty = { [K in 'EASY' | 'NORMAL']: string }; +``` ### Conclusion @@ -63,5 +73,5 @@ Enums are not redundant, but in most cases union types are preferred. Unless you The goal of this challenge is to refactor the enums `Difficulty` & `Direction`. -- Refactor `Difficulty` to const enum. -- Refactor `Direction` to union type. +- Refactor `Difficulty` enum to **union type**. +- Refactor `Direction` enum to **mapped type**. From 7918f4deb9ea613c8816fb792de7022a2b4e07a1 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Sun, 3 Mar 2024 16:40:34 +0100 Subject: [PATCH 062/361] docs(enums-vs-union-types): update docs content (const enums) --- .../docs/challenges/typescript/47-enums-vs-union-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md index b918c391d..194f6891a 100644 --- a/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md +++ b/docs/src/content/docs/challenges/typescript/47-enums-vs-union-types.md @@ -33,7 +33,7 @@ Enums are a concept borrowed from languages like C# and Java. TypeScript Enums a Enums have some more pitfalls as well: - Non-const enums do not fit to the concept "a typed superset of JavaScript". They violate the concept by emitting JavaScript objects that live in runtime with a syntax that is not compatible with JavaScript. -- Const enums in contrast cannot be transpiled with Babel. But there are workarounds for this issue, e. g. using `babel-plugin-const-enum` plugin. +- Const enums in contrast cannot be transpiled with Babel. But there are workarounds for this issue, e. g. using `babel-plugin-const-enum` plugin. The TypeScript documentation about [const enums](https://www.typescriptlang.org/docs/handbook/enums.html#const-enums) says "_Do not use const enums at all_". - To use enums you have to import them, if you want to use enum values in a template, you'll need to declare a variable in your component too. - Numeric enums are not type safe ... From cdf55200bc6e82cabbce70461b87a469b834a80e Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Mon, 4 Mar 2024 00:31:50 +0100 Subject: [PATCH 063/361] docs(testing-harness): update content --- .../content/docs/challenges/testing/23-harness.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/src/content/docs/challenges/testing/23-harness.md b/docs/src/content/docs/challenges/testing/23-harness.md index 5ea983483..e098b2208 100644 --- a/docs/src/content/docs/challenges/testing/23-harness.md +++ b/docs/src/content/docs/challenges/testing/23-harness.md @@ -8,13 +8,17 @@ sidebar: order: 9 --- -## Statement: +## Information -The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses. - -The goal is to test the functionality of `child.component.ts`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. +A component harness is a class that lets a test interact with a component via a supported API. -**Note:** You are welcome to use Testing Library if you wish. +The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses. Documentation for CDK Component Harness is [here](https://material.angular.io/cdk/test-harnesses/overview#api-for-test-authors). Documentation for Angular Material component is [here](https://material.angular.io/components/button/overview). + +## Statement + +The goal is to test the functionality of `child.component.ts`, which consists of some inputs & checkboxes related to a `mat-slider`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. + +**Note:** You are welcome to use Testing Library if you wish. From 80946becf9fc6bad5d34db6ff1f7bc6457ec5ff5 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Mon, 4 Mar 2024 00:35:23 +0100 Subject: [PATCH 064/361] docs(testing-harness): update content --- .../content/docs/challenges/testing/23-harness.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/src/content/docs/challenges/testing/23-harness.md b/docs/src/content/docs/challenges/testing/23-harness.md index 5ea983483..e098b2208 100644 --- a/docs/src/content/docs/challenges/testing/23-harness.md +++ b/docs/src/content/docs/challenges/testing/23-harness.md @@ -8,13 +8,17 @@ sidebar: order: 9 --- -## Statement: +## Information -The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses. - -The goal is to test the functionality of `child.component.ts`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. +A component harness is a class that lets a test interact with a component via a supported API. -**Note:** You are welcome to use Testing Library if you wish. +The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses. Documentation for CDK Component Harness is [here](https://material.angular.io/cdk/test-harnesses/overview#api-for-test-authors). Documentation for Angular Material component is [here](https://material.angular.io/components/button/overview). + +## Statement + +The goal is to test the functionality of `child.component.ts`, which consists of some inputs & checkboxes related to a `mat-slider`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. + +**Note:** You are welcome to use Testing Library if you wish. From 17330a0da067d08b8e0d54b03d68a46be478835d Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Mon, 4 Mar 2024 09:39:36 +0100 Subject: [PATCH 065/361] docs(testing-harness): update content (2) --- docs/src/content/docs/challenges/testing/19-input-output.md | 2 +- docs/src/content/docs/challenges/testing/20-modal.md | 2 +- docs/src/content/docs/challenges/testing/23-harness.md | 2 +- docs/src/content/docs/challenges/testing/29-real-application.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/content/docs/challenges/testing/19-input-output.md b/docs/src/content/docs/challenges/testing/19-input-output.md index 56456d483..6468c6c00 100644 --- a/docs/src/content/docs/challenges/testing/19-input-output.md +++ b/docs/src/content/docs/challenges/testing/19-input-output.md @@ -8,7 +8,7 @@ sidebar: order: 110 --- -## Information: +## Information We have a small counter application that increments or decrements a number. The `CounterComponent` takes an initial value as an `@Input` and emits the result of the counter as an `@Output` when we click on the **Send** button. Since we are testing our component as a black box, we only have access to our inputs and listen to the output values. We should not rely on any internal implementation details!!! diff --git a/docs/src/content/docs/challenges/testing/20-modal.md b/docs/src/content/docs/challenges/testing/20-modal.md index c3d7c3f2d..93f32c288 100644 --- a/docs/src/content/docs/challenges/testing/20-modal.md +++ b/docs/src/content/docs/challenges/testing/20-modal.md @@ -8,7 +8,7 @@ sidebar: order: 111 --- -## Information: +## Information In this small application, you have an input prompting you to enter a name, and a **Confirm** button to submit your form. If you enter a name, a confirmation modal will appear; otherwise an error modal will be displayed. diff --git a/docs/src/content/docs/challenges/testing/23-harness.md b/docs/src/content/docs/challenges/testing/23-harness.md index e098b2208..bdb9ce3ac 100644 --- a/docs/src/content/docs/challenges/testing/23-harness.md +++ b/docs/src/content/docs/challenges/testing/23-harness.md @@ -19,6 +19,6 @@ Documentation for Angular Material component is [here](https://material.angular. ## Statement -The goal is to test the functionality of `child.component.ts`, which consists of some inputs & checkboxes related to a `mat-slider`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. +Test the functionality of `child.component.ts`, which consists of some inputs & checkboxes related to a `mat-slider`. Implement the prepared test suite, but feel free to include additional tests as well. **Note:** You are welcome to use Testing Library if you wish. diff --git a/docs/src/content/docs/challenges/testing/29-real-application.md b/docs/src/content/docs/challenges/testing/29-real-application.md index 1d64fb964..e05edd720 100644 --- a/docs/src/content/docs/challenges/testing/29-real-application.md +++ b/docs/src/content/docs/challenges/testing/29-real-application.md @@ -8,7 +8,7 @@ sidebar: order: 205 --- -## Information: +## Information This application presents a greater challenge because it closely resembles a real-life application that you might encounter in your day-to-day activities as an Angular developer. What makes it more difficult is the need to handle asynchronous tasks and create appropriate mocks. From 0525a7d7a5a363a9c2d04aea087fbd33a716a825 Mon Sep 17 00:00:00 2001 From: thomas Date: Tue, 5 Mar 2024 09:01:28 +0100 Subject: [PATCH 066/361] fix: main screen --- docs/src/content/docs/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 1e1d132c1..6a2e615c6 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Go to the latest Challenge - link: /challenges/angular/46-simple-animations/ + link: /challenges/typescript/47-enums-vs-union-types/ icon: rocket - text: Give a star link: https://github.com/tomalaforge/angular-challenges From 4dee8420ffe8a6fd78a68216fb29679977dd6f63 Mon Sep 17 00:00:00 2001 From: Sven Brodny Date: Tue, 5 Mar 2024 10:12:27 +0100 Subject: [PATCH 067/361] docs(simple-animations): update solution previews --- .../content/docs/challenges/angular/46-simple-animations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/content/docs/challenges/angular/46-simple-animations.md b/docs/src/content/docs/challenges/angular/46-simple-animations.md index 9a92e89ff..b562755af 100644 --- a/docs/src/content/docs/challenges/angular/46-simple-animations.md +++ b/docs/src/content/docs/challenges/angular/46-simple-animations.md @@ -35,12 +35,12 @@ The goal of this challenge is to add animations, they should run when the user a Add a fading or moving animation for the paragraphs on the left side. -