mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 12:53:03 -05:00
Merge branch 'main' into add-challenge-simple-animations
This commit is contained in:
@@ -79,6 +79,15 @@
|
|||||||
"translation-ru"
|
"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",
|
"login": "alan-bio",
|
||||||
"name": "Alan Dragicevich",
|
"name": "Alan Dragicevich",
|
||||||
@@ -201,6 +210,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"doc"
|
"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,
|
"contributorsPerLine": 7,
|
||||||
|
|||||||
@@ -38,23 +38,25 @@ Check [all 45 challenges](https://angular-challenges.vercel.app/)
|
|||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jdegand"><img src="https://avatars.githubusercontent.com/u/70610011?v=4?s=100" width="100px;" alt="J. Degand"/><br /><sub><b>J. Degand</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=jdegand" title="Documentation">📖</a> <a href="#content-jdegand" title="Content">🖋</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=jdegand" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jdegand"><img src="https://avatars.githubusercontent.com/u/70610011?v=4?s=100" width="100px;" alt="J. Degand"/><br /><sub><b>J. Degand</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=jdegand" title="Documentation">📖</a> <a href="#content-jdegand" title="Content">🖋</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=jdegand" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DeveshChau"><img src="https://avatars.githubusercontent.com/u/9509673?v=4?s=100" width="100px;" alt="Devesh Chaudhari"/><br /><sub><b>Devesh Chaudhari</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=DeveshChau" title="Code">💻</a> <a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3ADeveshChau" title="Bug reports">🐛</a> <a href="#challenge-DeveshChau" title="Create a challenge">🧩</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DeveshChau"><img src="https://avatars.githubusercontent.com/u/9509673?v=4?s=100" width="100px;" alt="Devesh Chaudhari"/><br /><sub><b>Devesh Chaudhari</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=DeveshChau" title="Code">💻</a> <a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3ADeveshChau" title="Bug reports">🐛</a> <a href="#challenge-DeveshChau" title="Create a challenge">🧩</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stillst"><img src="https://avatars.githubusercontent.com/u/1463098?v=4?s=100" width="100px;" alt="stillst"/><br /><sub><b>stillst</b></sub></a><br /><a href="#challenge-stillst" title="Create a challenge">🧩</a> <a href="#translation-ru-stillst" title="Translate in Russian">🇷🇺</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stillst"><img src="https://avatars.githubusercontent.com/u/1463098?v=4?s=100" width="100px;" alt="stillst"/><br /><sub><b>stillst</b></sub></a><br /><a href="#challenge-stillst" title="Create a challenge">🧩</a> <a href="#translation-ru-stillst" title="Translate in Russian">🇷🇺</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://wandrille-guesdon.com/"><img src="https://avatars.githubusercontent.com/u/15016833?v=4?s=100" width="100px;" alt="Wandrille"/><br /><sub><b>Wandrille</b></sub></a><br /><a href="#challenge-wandri" title="Create a challenge">🧩</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alan-bio"><img src="https://avatars.githubusercontent.com/u/31838230?v=4?s=100" width="100px;" alt="Alan Dragicevich"/><br /><sub><b>Alan Dragicevich</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=alan-bio" title="Documentation">📖</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alan-bio"><img src="https://avatars.githubusercontent.com/u/31838230?v=4?s=100" width="100px;" alt="Alan Dragicevich"/><br /><sub><b>Alan Dragicevich</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=alan-bio" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/edimitchel"><img src="https://avatars.githubusercontent.com/u/2922851?v=4?s=100" width="100px;" alt="Michel EDIGHOFFER"/><br /><sub><b>Michel EDIGHOFFER</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=edimitchel" title="Documentation">📖</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/edimitchel"><img src="https://avatars.githubusercontent.com/u/2922851?v=4?s=100" width="100px;" alt="Michel EDIGHOFFER"/><br /><sub><b>Michel EDIGHOFFER</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=edimitchel" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gsgonzalez88"><img src="https://avatars.githubusercontent.com/u/39884678?v=4?s=100" width="100px;" alt="Gerardo Sebastian Gonzalez"/><br /><sub><b>Gerardo Sebastian Gonzalez</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=gsgonzalez88" title="Documentation">📖</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gsgonzalez88"><img src="https://avatars.githubusercontent.com/u/39884678?v=4?s=100" width="100px;" alt="Gerardo Sebastian Gonzalez"/><br /><sub><b>Gerardo Sebastian Gonzalez</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=gsgonzalez88" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marryday"><img src="https://avatars.githubusercontent.com/u/57489315?v=4?s=100" width="100px;" alt="Evseev Yuriy"/><br /><sub><b>Evseev Yuriy</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3Amarryday" title="Bug reports">🐛</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marryday"><img src="https://avatars.githubusercontent.com/u/57489315?v=4?s=100" width="100px;" alt="Evseev Yuriy"/><br /><sub><b>Evseev Yuriy</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3Amarryday" title="Bug reports">🐛</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomer953"><img src="https://avatars.githubusercontent.com/u/1807493?v=4?s=100" width="100px;" alt="Tomer953"/><br /><sub><b>Tomer953</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3Atomer953" title="Bug reports">🐛</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=tomer953" title="Documentation">📖</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=tomer953" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tomer953"><img src="https://avatars.githubusercontent.com/u/1807493?v=4?s=100" width="100px;" alt="Tomer953"/><br /><sub><b>Tomer953</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3Atomer953" title="Bug reports">🐛</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=tomer953" title="Documentation">📖</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=tomer953" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dmmishchenko"><img src="https://avatars.githubusercontent.com/u/51910160?v=4?s=100" width="100px;" alt="Dmitriy Mishchenko"/><br /><sub><b>Dmitriy Mishchenko</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=dmmishchenko" title="Documentation">📖</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dmmishchenko"><img src="https://avatars.githubusercontent.com/u/51910160?v=4?s=100" width="100px;" alt="Dmitriy Mishchenko"/><br /><sub><b>Dmitriy Mishchenko</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=dmmishchenko" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="http://www.sagardev.com.np"><img src="https://avatars.githubusercontent.com/u/30800393?v=4?s=100" width="100px;" alt="Sagar Devkota"/><br /><sub><b>Sagar Devkota</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Documentation">📖</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="http://www.sagardev.com.np"><img src="https://avatars.githubusercontent.com/u/30800393?v=4?s=100" width="100px;" alt="Sagar Devkota"/><br /><sub><b>Sagar Devkota</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Documentation">📖</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://nelsonguti.dev/"><img src="https://avatars.githubusercontent.com/u/62297014?v=4?s=100" width="100px;" alt="Nelson Gutierrez"/><br /><sub><b>Nelson Gutierrez</b></sub></a><br /><a href="#translation-es-nelsongutidev" title="Translate in Spanish">🇪🇸</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://nelsonguti.dev/"><img src="https://avatars.githubusercontent.com/u/62297014?v=4?s=100" width="100px;" alt="Nelson Gutierrez"/><br /><sub><b>Nelson Gutierrez</b></sub></a><br /><a href="#translation-es-nelsongutidev" title="Translate in Spanish">🇪🇸</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ho-ssain"><img src="https://avatars.githubusercontent.com/u/61125174?v=4?s=100" width="100px;" alt="Hossain K. M."/><br /><sub><b>Hossain K. M.</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=ho-ssain" title="Documentation">📖</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ho-ssain"><img src="https://avatars.githubusercontent.com/u/61125174?v=4?s=100" width="100px;" alt="Hossain K. M."/><br /><sub><b>Hossain K. M.</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=ho-ssain" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kabrunko-dev/"><img src="https://avatars.githubusercontent.com/u/142346548?v=4?s=100" width="100px;" alt="Diogo Nishikawa"/><br /><sub><b>Diogo Nishikawa</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=kabrunko-dev" title="Code">💻</a> <a href="#translation-pt-kabrunko-dev" title="Translate in Portuguese">🇵🇹</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=kabrunko-dev" title="Documentation">📖</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kabrunko-dev/"><img src="https://avatars.githubusercontent.com/u/142346548?v=4?s=100" width="100px;" alt="Diogo Nishikawa"/><br /><sub><b>Diogo Nishikawa</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=kabrunko-dev" title="Code">💻</a> <a href="#translation-pt-kabrunko-dev" title="Translate in Portuguese">🇵🇹</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=kabrunko-dev" title="Documentation">📖</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="http://www.streamoverlaypro.com"><img src="https://avatars.githubusercontent.com/u/1978642?v=4?s=100" width="100px;" alt="Erick Rodriguez"/><br /><sub><b>Erick Rodriguez</b></sub></a><br /><a href="#translation-es-ErickRodrCodes" title="Translate in Spanish">🇪🇸</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="http://www.streamoverlaypro.com"><img src="https://avatars.githubusercontent.com/u/1978642?v=4?s=100" width="100px;" alt="Erick Rodriguez"/><br /><sub><b>Erick Rodriguez</b></sub></a><br /><a href="#translation-es-ErickRodrCodes" title="Translate in Spanish">🇪🇸</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://eduardoroth.dev"><img src="https://avatars.githubusercontent.com/u/5419161?v=4?s=100" width="100px;" alt="Eduardo Roth"/><br /><sub><b>Eduardo Roth</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=eduardoRoth" title="Documentation">📖</a> <a href="#translation-es-eduardoRoth" title="Translate in Spanish">🇪🇸</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://eduardoroth.dev"><img src="https://avatars.githubusercontent.com/u/5419161?v=4?s=100" width="100px;" alt="Eduardo Roth"/><br /><sub><b>Eduardo Roth</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=eduardoRoth" title="Documentation">📖</a> <a href="#translation-es-eduardoRoth" title="Translate in Spanish">🇪🇸</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1fbr"><img src="https://avatars.githubusercontent.com/u/63980689?v=4?s=100" width="100px;" alt="Fernando Bello"/><br /><sub><b>Fernando Bello</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=1fbr" title="Documentation">📖</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1fbr"><img src="https://avatars.githubusercontent.com/u/63980689?v=4?s=100" width="100px;" alt="Fernando Bello"/><br /><sub><b>Fernando Bello</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=1fbr" title="Documentation">📖</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://svenson95.github.io/sb-portfolio/"><img src="https://avatars.githubusercontent.com/u/46655156?v=4?s=100" width="100px;" alt="Sven Brodny"/><br /><sub><b>Sven Brodny</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=svenson95" title="Documentation">📖</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
|
|||||||
36
apps/angular/react-in-angular/.eslintrc.json
Normal file
36
apps/angular/react-in-angular/.eslintrc.json
Normal file
@@ -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": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/angular/react-in-angular/README.md
Normal file
13
apps/angular/react-in-angular/README.md
Normal file
@@ -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/).
|
||||||
22
apps/angular/react-in-angular/jest.config.ts
Normal file
22
apps/angular/react-in-angular/jest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
displayName: 'angular-react-in-angular',
|
||||||
|
preset: '../../../jest.preset.js',
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||||
|
coverageDirectory: '../../../coverage/apps/angular/react-in-angular',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.(ts|mjs|js|html)$': [
|
||||||
|
'jest-preset-angular',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||||
|
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||||
|
snapshotSerializers: [
|
||||||
|
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||||
|
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||||
|
'jest-preset-angular/build/serializers/html-comment',
|
||||||
|
],
|
||||||
|
};
|
||||||
80
apps/angular/react-in-angular/project.json
Normal file
80
apps/angular/react-in-angular/project.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
apps/angular/react-in-angular/src/app/app.component.ts
Normal file
62
apps/angular/react-in-angular/src/app/app.component.ts
Normal file
@@ -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: `
|
||||||
|
<div class="flex flex-col gap-2 p-12">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
@for (post of posts; track post.title) {
|
||||||
|
<div class="rounded-lg bg-gray-100 p-4">
|
||||||
|
<app-post
|
||||||
|
(selectPost)="selectPost(post)"
|
||||||
|
[post]="post"
|
||||||
|
[isSelected]="post.title === selectedPost()?.title"></app-post>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-2 border p-4">
|
||||||
|
<span class="text-xs font-medium">Selected Post:</span>
|
||||||
|
<span class="text-lg text-blue-700">
|
||||||
|
{{ selectedPost()?.title ?? '-' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
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<Post | null>(null);
|
||||||
|
|
||||||
|
selectPost(post: Post) {
|
||||||
|
this.selectedPost.set(post);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
apps/angular/react-in-angular/src/app/app.config.ts
Normal file
5
apps/angular/react-in-angular/src/app/app.config.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { ApplicationConfig } from '@angular/core';
|
||||||
|
|
||||||
|
export const appConfig: ApplicationConfig = {
|
||||||
|
providers: [],
|
||||||
|
};
|
||||||
27
apps/angular/react-in-angular/src/app/react/ReactPost.tsx
Normal file
27
apps/angular/react-in-angular/src/app/react/ReactPost.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// import React from 'react';
|
||||||
|
|
||||||
|
export default function ReactPost(props: {
|
||||||
|
title?: string,
|
||||||
|
description?: string,
|
||||||
|
pictureLink?: string,
|
||||||
|
selected?: boolean,
|
||||||
|
handleClick: () => void
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={props.selected ? 'bg-blue-100' : 'bg-white'}>
|
||||||
|
<div className="max-w-sm rounded overflow-hidden shadow-lg">
|
||||||
|
<img className="w-full h-32 object-cover" src={props.pictureLink} alt={props.title}></img>
|
||||||
|
<div className="px-6 py-4 flex flex-col gap-2">
|
||||||
|
<div className="font-bold text-xl mb-2">{props.title}</div>
|
||||||
|
<p className="text-gray-700 text-base">
|
||||||
|
{props.description}
|
||||||
|
</p>
|
||||||
|
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
||||||
|
onClick={props.handleClick}>
|
||||||
|
Select
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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: `
|
||||||
|
<div></div>
|
||||||
|
`,
|
||||||
|
styles: [''],
|
||||||
|
})
|
||||||
|
export class PostComponent {
|
||||||
|
post = input<Post | undefined>(undefined);
|
||||||
|
isSelected = input<boolean>(false);
|
||||||
|
@Output() selectPost = new EventEmitter<void>();
|
||||||
|
}
|
||||||
0
apps/angular/react-in-angular/src/assets/.gitkeep
Normal file
0
apps/angular/react-in-angular/src/assets/.gitkeep
Normal file
BIN
apps/angular/react-in-angular/src/favicon.ico
Normal file
BIN
apps/angular/react-in-angular/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
13
apps/angular/react-in-angular/src/index.html
Normal file
13
apps/angular/react-in-angular/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>angular-react-in-angular</title>
|
||||||
|
<base href="/" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
7
apps/angular/react-in-angular/src/main.ts
Normal file
7
apps/angular/react-in-angular/src/main.ts
Normal file
@@ -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),
|
||||||
|
);
|
||||||
5
apps/angular/react-in-angular/src/styles.scss
Normal file
5
apps/angular/react-in-angular/src/styles.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* You can add global styles to this file, and also import other style files */
|
||||||
2
apps/angular/react-in-angular/src/test-setup.ts
Normal file
2
apps/angular/react-in-angular/src/test-setup.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import '@testing-library/jest-dom';
|
||||||
|
import 'jest-preset-angular/setup-jest';
|
||||||
14
apps/angular/react-in-angular/tailwind.config.js
Normal file
14
apps/angular/react-in-angular/tailwind.config.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
|
||||||
|
...createGlobPatternsForDependencies(__dirname),
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
10
apps/angular/react-in-angular/tsconfig.app.json
Normal file
10
apps/angular/react-in-angular/tsconfig.app.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../dist/out-tsc",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"files": ["src/main.ts"],
|
||||||
|
"include": ["src/**/*.d.ts"],
|
||||||
|
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
|
||||||
|
}
|
||||||
7
apps/angular/react-in-angular/tsconfig.editor.json
Normal file
7
apps/angular/react-in-angular/tsconfig.editor.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
}
|
||||||
|
}
|
||||||
33
apps/angular/react-in-angular/tsconfig.json
Normal file
33
apps/angular/react-in-angular/tsconfig.json
Normal file
@@ -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,
|
||||||
|
},
|
||||||
|
}
|
||||||
15
apps/angular/react-in-angular/tsconfig.spec.json
Normal file
15
apps/angular/react-in-angular/tsconfig.spec.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node", "@testing-library/jest-dom"]
|
||||||
|
},
|
||||||
|
"files": ["src/test-setup.ts"],
|
||||||
|
"include": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import { Component, input } from '@angular/core';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgOptimizedImage],
|
imports: [NgOptimizedImage],
|
||||||
template: `
|
template: `
|
||||||
<!-- <div class="flex flex-col gap-3">-->
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img
|
<img
|
||||||
ngSrc="assets/profil.webp"
|
ngSrc="assets/profil.webp"
|
||||||
@@ -23,7 +22,6 @@ import { Component, input } from '@angular/core';
|
|||||||
</div>
|
</div>
|
||||||
<span class="text-md mt-2 font-bold uppercase">Thomas Laforge</span>
|
<span class="text-md mt-2 font-bold uppercase">Thomas Laforge</span>
|
||||||
<span class="text-sm">{{ date() }}</span>
|
<span class="text-sm">{{ date() }}</span>
|
||||||
<!-- </div>-->
|
|
||||||
`,
|
`,
|
||||||
host: {
|
host: {
|
||||||
class: 'flex flex-col justify-center items-center',
|
class: 'flex flex-col justify-center items-center',
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"total": 45,
|
"total": 45,
|
||||||
"🟢": 17,
|
"🟢": 17,
|
||||||
"🟠": 120,
|
"🟠": 120,
|
||||||
"🔴": 208
|
"🔴": 209
|
||||||
}
|
}
|
||||||
|
|||||||
5
docs/src/content/authors/wandrille-guesdon.json
Normal file
5
docs/src/content/authors/wandrille-guesdon.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Wandrille Guesdon",
|
||||||
|
"linkedin": "https://www.linkedin.com/in/wandrille-guesdon-53a54684/",
|
||||||
|
"github": "https://github.com/wandri"
|
||||||
|
}
|
||||||
@@ -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))
|
- 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))
|
- 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))
|
||||||
|
|||||||
@@ -8,14 +8,27 @@ sidebar:
|
|||||||
order: 202
|
order: 202
|
||||||
---
|
---
|
||||||
|
|
||||||
The goal of this series of 3 pipe challenges is to master **pipe** in Angular.
|
## Information
|
||||||
|
|
||||||
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.
|
This is the third of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular.
|
||||||
|
|
||||||
## Information:
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Constraints:
|
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.
|
||||||
|
|
||||||
- must be strongly typed
|
:::note
|
||||||
|
A **pure** pipe is only called when 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).
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
- Must be strongly typed
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ In version 16, Angular introduced a new `Input` that can listen to route data. Y
|
|||||||
|
|
||||||
## Statement
|
## 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.
|
||||||
|
|||||||
@@ -10,20 +10,20 @@ sidebar:
|
|||||||
---
|
---
|
||||||
|
|
||||||
:::note
|
:::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
|
## 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.
|
But the real power is that you can enhance an already existing directive which moreover doesn't **belong** to you.
|
||||||
|
|
||||||
## Statement
|
## 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 :
|
Currently we have:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
<ng-container *ngIf="persons.length > 0; else emptyList">
|
<ng-container *ngIf="persons.length > 0; else emptyList">
|
||||||
@@ -34,7 +34,7 @@ Currently we have :
|
|||||||
<ng-template #emptyList>The list is empty !!</ng-template>
|
<ng-template #emptyList>The list is empty !!</ng-template>
|
||||||
```
|
```
|
||||||
|
|
||||||
We want to get rid of the ng-container by writing :
|
We want to get rid of the `ng-container` by writing:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
<div *ngFor="let person of persons; empty: emptyList">
|
<div *ngFor="let person of persons; empty: emptyList">
|
||||||
@@ -43,4 +43,4 @@ We want to get rid of the ng-container by writing :
|
|||||||
<ng-template #emptyList>The list is empty !!</ng-template>
|
<ng-template #emptyList>The list is empty !!</ng-template>
|
||||||
```
|
```
|
||||||
|
|
||||||
The goal is to **improve the ngFor directive**
|
The goal is to **improve the ngFor directive**.
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ However the context of **NgTemplateOutlet** type is **Object**. But with the hel
|
|||||||
|
|
||||||
## Statement
|
## 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
|
### Level 1: known Interface
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
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: 209
|
||||||
|
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 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
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hint 1 - Configuration</summary>
|
||||||
|
Allow the React files in tsconfig.json
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"compilerOptions": {
|
||||||
|
...
|
||||||
|
"jsx": "react"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hint 2 - Initialization</summary>
|
||||||
|
Create a react root with `createRoot(...)`
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hint 3 - Display</summary>
|
||||||
|
To render the component, it should look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
<react root>.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
...
|
||||||
|
</React.StrictMode>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hint 4 - Design</summary>
|
||||||
|
Do not forget to allow the react file in Tailwind.
|
||||||
|
</details>
|
||||||
@@ -14,7 +14,7 @@ Communicating and having a global/local state in sync with your backend is the h
|
|||||||
|
|
||||||
## Statement
|
## 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.
|
Currently we have a working example but filled with lots of bad practices.
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,27 @@ sidebar:
|
|||||||
order: 3
|
order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
The goal of this series of 3 pipe challenges is to master **pipe** 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.
|
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|
||||||
In this first exercice, you call a simple function inside your template. The goal is to convert it to a pipe.
|
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.
|
||||||
|
|
||||||
|
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 when 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).
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
## Constraints
|
## Constraints
|
||||||
|
|
||||||
- must be strongly typed
|
- Must be strongly typed
|
||||||
|
|||||||
@@ -9,15 +9,28 @@ sidebar:
|
|||||||
order: 103
|
order: 103
|
||||||
---
|
---
|
||||||
|
|
||||||
The goal of this series of 3 pipe challenges is to master **pipe** in Angular.
|
## Information
|
||||||
|
|
||||||
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.
|
This is the second of three `@Pipe()` challenges, the goal of this series is to master **pipes** in Angular.
|
||||||
|
|
||||||
## Information:
|
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.
|
||||||
|
|
||||||
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.
|
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 when 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).
|
||||||
|
|
||||||
|
## Statement
|
||||||
|
|
||||||
|
In this exercise, you are calling multiple functions inside your template. You can create a specific pipe for each of the functions but this will be too cumbersome.
|
||||||
The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.**
|
The goal is to create a `wrapFn` pipe to wrap your callback function though a pipe. Your function MUST remain inside your component. **`WrapFn` must be highly reusable.**
|
||||||
|
|
||||||
## Constraints:
|
## Constraints:
|
||||||
|
|
||||||
- must be strongly typed
|
- Must be strongly typed
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ sidebar:
|
|||||||
order: 113
|
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
|
## Information
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ hero:
|
|||||||
icon: right-arrow
|
icon: right-arrow
|
||||||
variant: primary
|
variant: primary
|
||||||
- text: Go to the latest Challenge
|
- text: Go to the latest Challenge
|
||||||
link: /challenges/angular/44-view-transition/
|
link: /challenges/angular/45-react-in-angular/
|
||||||
icon: rocket
|
icon: rocket
|
||||||
- text: Give a star
|
- text: Give a star
|
||||||
link: https://github.com/tomalaforge/angular-challenges
|
link: https://github.com/tomalaforge/angular-challenges
|
||||||
|
|||||||
@@ -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
|
||||||
|
<ng-container *ngIf="persons.length > 0; else emptyList">
|
||||||
|
<div *ngFor="let person of persons">
|
||||||
|
{{ person.name }}
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #emptyList>The list is empty !!</ng-template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Queremos nos livrar do `ng-container` escrevendo:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
<div *ngFor="let person of persons; empty: emptyList">
|
||||||
|
{{ person.name }}
|
||||||
|
</div>
|
||||||
|
<ng-template #emptyList>The list is empty !!</ng-template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Objetivo é **melhorar a diretiva ngFor**.
|
||||||
@@ -6,7 +6,6 @@ challengeNumber: 44
|
|||||||
command: angular-view-transition
|
command: angular-view-transition
|
||||||
sidebar:
|
sidebar:
|
||||||
order: 208
|
order: 208
|
||||||
badge: New
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Informação
|
## Informação
|
||||||
|
|||||||
Reference in New Issue
Block a user