From 0a2229971eaff29ada1638b750bd7025662c0b9b Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Thu, 8 Feb 2024 16:57:11 -0300 Subject: [PATCH 01/29] docs(pt): translate challenge 3 --- .../angular/3-directive-enhancement.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/src/content/docs/pt/challenges/angular/3-directive-enhancement.md diff --git a/docs/src/content/docs/pt/challenges/angular/3-directive-enhancement.md b/docs/src/content/docs/pt/challenges/angular/3-directive-enhancement.md new file mode 100644 index 0000000..808f997 --- /dev/null +++ b/docs/src/content/docs/pt/challenges/angular/3-directive-enhancement.md @@ -0,0 +1,46 @@ +--- +title: 🟠 Aprimoramento de Diretiva +description: Desafio 3 é sobre o aprimoramento de uma diretiva nativa +author: thomas-laforge +challengeNumber: 3 +command: angular-ngfor-enhancement +blogLink: https://medium.com/@thomas.laforge/ngfor-enhancement-716b44656a6c +sidebar: + order: 101 +--- + +:::note[Nota] +Este exercício pode ser obsoleto com o novo controle de fluxo e do bloco de empty state dentro do bloco `@for`. No entanto, **diretivas estruturais** não serão removidas tão cedo, por isso você ainda pode aprender bastante com este exercício. +::: + +## Informação + +Diretiva é uma ferramente poderosa oferecida pelo framework Angular. Você pode usar o princípio DRY compartilhando a lógica dentro de uma diretiva e aplicando ela em qualquer componente que quiser. + +Mas a verdadeira vantagem é que você consegue melhorar uma diretiva pré-existente que não **pertence** a você. + +## Declaração + +Neste exercício, queremos mostrar uma lista de pessoas. Se a lista está vazio, você deve mostrar _" the list is empty !! "_. + +Atualmente, temos: + +```typescript + +
+ {{ person.name }} +
+
+ The list is empty !! +``` + +Queremos nos livrar do `ng-container` escrevendo: + +```typescript +
+ {{ person.name }} +
+ The list is empty !! +``` + +Objetivo é **melhorar a diretiva ngFor**. From 77c7476bfa67eaaa0333d010dce94319dbdbeaa5 Mon Sep 17 00:00:00 2001 From: kabrunko-dev Date: Thu, 8 Feb 2024 18:11:06 -0300 Subject: [PATCH 02/29] docs(en): fit typo Also remove whitespaces before colons and add code highlight on word 'ng-container' --- .../docs/challenges/angular/3-directive-enhancement.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 41a0cad..3f89860 100644 --- a/docs/src/content/docs/challenges/angular/3-directive-enhancement.md +++ b/docs/src/content/docs/challenges/angular/3-directive-enhancement.md @@ -15,7 +15,7 @@ This exercice can feel obsolete with the new control flow and the empty block in ## Information -Directive is a very powerful tool only offered by the Angular framework. You can apply the DRY principal by having shared logic inside a directive and applying it to any component you want. +Directive is a very powerful tool only offered by the Angular framework. You can apply the DRY principle by having shared logic inside a directive and applying it to any component you want. But the real power is that you can enhance an already existing directive which moreover doesn't **belong** to you. @@ -23,7 +23,7 @@ But the real power is that you can enhance an already existing directive which m 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 !! "_. -Currently we have : +Currently we have: ```typescript @@ -34,7 +34,7 @@ Currently we have : The list is empty !! ``` -We want to get rid of the ng-container by writing : +We want to get rid of the `ng-container` by writing: ```typescript
@@ -43,4 +43,4 @@ We want to get rid of the ng-container by writing : The list is empty !! ``` -The goal is to **improve the ngFor directive** +The goal is to **improve the ngFor directive**. From 0f4f14c3518e310f7203ae01e5350f781598e0d6 Mon Sep 17 00:00:00 2001 From: Wandrille Date: Fri, 9 Feb 2024 09:25:05 +0100 Subject: [PATCH 03/29] 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 1e43bdf..de88144 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 0000000..8ebcbfd --- /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 0000000..0a8679a --- /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 0000000..92d5f25 --- /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 0000000..8153ec8 --- /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 0000000..a914cc6 --- /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 0000000..81a6edd --- /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 0000000..6ff7b4d --- /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 0000000..2a35eac --- /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 0000000..e69de29 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 0000000..f3a7223 --- /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 0000000..77e408a --- /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 0000000..15de72a --- /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 0000000..38183db --- /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 0000000..5822042 --- /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 0000000..8ae117d --- /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 0000000..7a9f4b7 --- /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 0000000..1a4817a --- /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 a48a4f1..6970465 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 0000000..6aae8fb --- /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 e164844..ce07092 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 892cda6..2388d8d 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 968084a..7185c30 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 3004dae..a2bd9bb 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 ac0cb90..349ac70 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 04/29] 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 6ff7b4d..a49d932 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 0000000..882e21b --- /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 38183db..99b4c14 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 7a9f4b7..3c5ef57 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 7952718..b292ca4 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 3507f1b..a4aa3dd 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 05/29] 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 a49d932..6ff7b4d 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 882e21b..0000000 --- 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 99b4c14..38183db 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 3c5ef57..7a9f4b7 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 b292ca4..7952718 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 a4aa3dd..3507f1b 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 06/29] 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 0000000..a240cba --- /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 07/29] 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 6aae8fb..e71ab68 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 08/29] 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 46ae580..6dbf211 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 e71ab68..96443c7 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 7391bb4..ead29d4 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 09/29] 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 7185c30..b9a5715 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 10/29] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de88144..3fc04fb 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 11/29] docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 38856b4..5c281a2 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 12/29] 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 5c281a2..062fd18 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 3fc04fb..d8662ab 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 13/29] 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 f8688dd..bab3886 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 75ac297..59676ce 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 41a0cad..3c8182c 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 43f8a2d..88d4e5b 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 dfc909f..9d34d5a 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 58620cb..04fe2c6 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 a50aa09..2048f35 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 f571bbf..ea7914b 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 14/29] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d8662ab..a350212 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 15/29] docs: update .all-contributorsrc --- .all-contributorsrc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 062fd18..5e94f8a 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 16/29] 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 1602510..f3409b1 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 17/29] 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 f8688dd..6e13733 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 58620cb..6e5b11a 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 a50aa09..9c97bcd 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 18/29] 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 3c19fa1..73fef04 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 19/29] 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 73fef04..e7bd6b5 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 20/29] 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 e7bd6b5..efa51d5 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 21/29] 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 efa51d5..3c19fa1 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 22/29] 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 6e13733..f356ec0 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 6e5b11a..529ff1f 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 9c97bcd..350a6d2 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 23/29] 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 f356ec0..24e469d 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 24/29] 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 529ff1f..e69f833 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 350a6d2..6f45766 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 25/29] 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 24e469d..f10d9f3 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 e69f833..79b58a8 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 6f45766..4d75ef1 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 26/29] 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 79b58a8..e6871a4 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 27/29] 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 96443c7..4ace12e 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 28/29] 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 db2f42d..8b62a6c 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 29/29] 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 4ace12e..3c56d88 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 ```