Merge branch 'docs-pipes-changes' of https://github.com/svenson95/angular-challenges into docs-pipes-changes

This commit is contained in:
Sven Brodny
2024-02-16 22:19:16 +01:00
38 changed files with 572 additions and 54 deletions

View File

@@ -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,6 +210,15 @@
"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,

View File

@@ -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 ✨
@@ -38,23 +38,25 @@ Check [all 44 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/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://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/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>
<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/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="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://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>
<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="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://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>
</tbody>
<tfoot>

View 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": {}
}
]
}

View 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/).

View 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',
],
};

View 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"
}
}
}
}

View 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);
}
}

View File

@@ -0,0 +1,5 @@
import { ApplicationConfig } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [],
};

View 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>
);
}

View File

@@ -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>();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View 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>

View 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),
);

View 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 */

View File

@@ -0,0 +1,2 @@
import '@testing-library/jest-dom';
import 'jest-preset-angular/setup-jest';

View 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: [],
};

View 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"]
}

View File

@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.json",
"include": ["src/**/*.ts"],
"compilerOptions": {
"types": ["jest", "node"]
}
}

View 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,
},
}

View 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"
]
}

View File

@@ -1,6 +1,6 @@
{
"total": 44,
"total": 45,
"🟢": 16,
"🟠": 120,
"🔴": 208
"🔴": 209
}

View File

@@ -0,0 +1,5 @@
{
"name": "Wandrille Guesdon",
"linkedin": "https://www.linkedin.com/in/wandrille-guesdon-53a54684/",
"github": "https://github.com/wandri"
}

View File

@@ -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))

View File

@@ -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.

View File

@@ -10,20 +10,20 @@ 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
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.
## 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
<ng-container *ngIf="persons.length > 0; else emptyList">
@@ -34,7 +34,7 @@ Currently we have :
<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
<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>
```
The goal is to **improve the ngFor directive**
The goal is to **improve the ngFor directive**.

View File

@@ -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

View File

@@ -6,7 +6,6 @@ challengeNumber: 44
command: angular-view-transition
sidebar:
order: 208
badge: New
---
## Information

View File

@@ -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 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
<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>

View File

@@ -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.

View File

@@ -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

View File

@@ -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';
<CardGrid>
<Card title="44 Desafíos">
Este repositorio contiene 44 desafíos relacionados con <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> y <b>Typescript</b>.
<Card title="45 Desafíos">
Este repositorio contiene 45 Desafíos relacionados con <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> y <b>Typescript</b>.
Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades.
</Card>
<Card title="Suscríbete para ser notificado sobre los últimos retos">
<SubscriptionForm isNote={false} lang="es"/>
<SubscriptionForm isNote={false} lang="es" />
</Card>
<Card title="Conviértete en un Contribuidor de OSS">
@@ -57,7 +57,8 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro'
</Card>
<Card title="Prepárate para Entrevistas">
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.
</Card>
<Card title="Patrocinio">

View File

@@ -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';
<CardGrid>
<Card title="44 Défis">
Ce répertoire rassemble 44 défis liés à <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> et <b>Typescript</b>. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
<Card title="45 Défis">
Ce répertoire rassemble 45 Défis liés à <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> et <b>Typescript</b>. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
</Card>
<Card title="Subscribe to get notify of latest challenges">
<SubscriptionForm isNote={false} lang="fr"/>
<SubscriptionForm isNote={false} lang="fr" />
</Card>
<Card title="Devenir un Mainteneur OSS">

View File

@@ -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
@@ -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';
<CardGrid>
<Card title="44 Challenges">
This repository gathers 44 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
<Card title="45 Challenges">
This repository gathers 45 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
These challenges resolve around real-life issues or specific features to elevate your skills.
</Card>
<Card title="Subscribe to get notify of latest challenges">
<SubscriptionForm isNote={false}/>
<SubscriptionForm isNote={false} />
</Card>
<Card title="Become an OSS Maintainer">

View File

@@ -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**.

View File

@@ -6,7 +6,6 @@ challengeNumber: 44
command: angular-view-transition
sidebar:
order: 208
badge: New
---
## Informação

View File

@@ -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';
<CardGrid>
<Card title="44 Desafios">
Este repositório possui 44 desafios relacionados a <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>,
<Card title="45 Desafios">
Este repositório possui 45 Desafios relacionados a <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>,
<b>Ngrx</b> e <b>Typescript</b>.
Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de
melhorar suas habilidades.
</Card>
<Card title="Inscreva-se para ser notificado do desafio mais recente">
<SubscriptionForm isNote={false} lang="pt"/>
</Card>
{' '}
<Card title="Inscreva-se para ser notificado do desafio mais recente">
<SubscriptionForm isNote={false} lang="pt" />
</Card>
{' '}

View File

@@ -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';
<CardGrid>
<Card title="44 Испытания">
Этот репозиторий содержит 44 испытания, связанных с <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
<Card title="45 Испытания">
Этот репозиторий содержит 45 Испытания, связанных с <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас.
</Card>
<Card title="Subscribe to get notify of latest challenges">
<SubscriptionForm isNote={false} lang="ru"/>
<SubscriptionForm isNote={false} lang="ru" />
</Card>
<Card title="Станьте мейнтейнером открытого программного обеспечения (OSS)">
Одна из целей этого репозитория <b>снизить барьер</b> для разработки
открытого программного обеспечения (OSS). Решив эти задачи, вы поймете,
как начать вносить свой вклад в любой другой проект с открытым исходным кодом.
Одна из целей этого репозитория <b>снизить барьер</b> для разработки открытого
программного обеспечения (OSS). Решив эти задачи, вы поймете, как начать
вносить свой вклад в любой другой проект с открытым исходным кодом.
</Card>
<Card title="Учитесь вместе с другими">
Изучение и использование нового фреймворка всегда сопряжено с трудностями.
В этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на практике то, чему вы научились.
Любой может оставить комментарий или предложить помощь.
Изучение и использование нового фреймворка всегда сопряжено с трудностями. В
этом наборе испытаний содержатся реальные примеры задач, чтобы закрепить на
практике то, чему вы научились. Любой может оставить комментарий или
предложить помощь.
<b>
Учиться одному - здорово, но обучение вместе с другими поможет вам добиться большего.
Учиться одному - здорово, но обучение вместе с другими поможет вам добиться
большего.
</b>
</Card>
<Card title="Вносите свой вклад">
У вас есть идея или интересный баг? Не стесняйтесь;{' '}
<b>Создавайте свои собственные испытания</b> не теряя времени.
<b>Создавайте свои собственные испытания</b> не теряя времени.
</Card>
<Card title="Подготовьтесь к собеседованию">
@@ -61,8 +63,9 @@ import SubscriptionForm from '../../../components/SubscriptionForm.astro'
</Card>
<Card title="Поддержка">
Это бесплатный проект, и он будет оставаться таковым как можно дольше.
Однако вся работа ведется в мое свободное время, включая создание новых испытаний и ревью их решений(PRs).
Это бесплатный проект, и он будет оставаться таковым как можно дольше. Однако
вся работа ведется в мое свободное время, включая создание новых испытаний и
ревью их решений(PRs).
<b>Спонсорство может поддержать меня и способствовать развитию проекта</b>.
</Card>