docs(doc): update all readme files

This commit is contained in:
thomas
2023-09-24 22:48:08 +02:00
parent 3d1ce3f3ad
commit 73297529ff
61 changed files with 1610 additions and 1079 deletions

View File

@@ -1,30 +1,13 @@
<h1>Anchor Scrolling</h1> # Anchor Navigation
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
You begin with an application that has basic navigation and anchor navigation in the `HomeComponent`. However, using `href` recreates the path each time and refreshes the page. ```bash
npx nx serve anchor-scrolling
```
### Statement ### Documentation and Instruction
- Your task is to refactor this application to use the built-in navigation tool to better fit within the Angular Framework. You can explore the router, but it's better to stay within the template and use the `RouterLink` directive. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/21-achor-scrolling.md/).
- To improve the user experience, add smooth scrolling.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve anchor-scrolling`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:21** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="anchor scrolling"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="anchor scrolling"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="DI blog article"/></a> -->
/
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,45 +1,13 @@
<h1>Bug Change Detection</h1> # Change Detection Bug
> Author: Thomas Laforge > Author: Thomas Laforge
This challenge is inspired by a real-life example that I simplified to create this nice challenge. ### Run Application
### Information ```bash
npx nx serve bug-cd
```
In this small application, we have a navigation menu to route our application to either `barComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console. ### Documentation and Instruction
### Statement Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular-performance/32-bug-cd.md/).
The goal of the challenge is to debug this application and make it work.
#### Hints
<details>
<summary>Hint 1</summary>
If you comment out `routerLinkActive="isSelected"` inside `NavigationComponent`: the application loads correctly.
</details>
<details>
<summary>Hint 2</summary>
If you open the [`RouterLinkActive` source code](https://github.com/angular/angular/blob/main/packages/router/src/directives/router_link_active.ts) and go to **line 196**, Angular is calling `this.cdr.markForCheck` inside a microTask which triggers a new CD cycle. If you comment out this line, the application loads again, however the bug is not inside the Angular Framework. 😅😯
</details>
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve bug-cd`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:32** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="bug-cd"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="bug-cd solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="bug-cd blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,49 +1,13 @@
<h1>NgTemplateOutlet Strongly Typed</h1> # Typed ContextOutlet
> Author: Thomas Laforge > Author: Thomas Laforge
## Information ### Run Application
Angular offer the static function **ngTemplateContextGuard** to strongly type structural directive. ```bash
npx nx serve context-outlet-type
```
However the context of **NgTemplateOutlet** type is **Object**. But which the help of the above guard, we can improve that behavior. ### Documentation and Instruction
## Statement Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/4-context-outlet-typed.md/).
In this exercice, we want to learn how to strongly typed our ng-template in our AppComponent.
This exercice has two level of complexity.
### Level 1: known Interface
Currently we have the following piece of code.
<img src="./img/unknown-person.png" height=120px alt="Unkown Person"/>
As we can see, name is of type "any". We want to infer the correct type.
### Level 2: generic Interface
Currently we have the following piece of code.
<img src="./img/unknown-student.png" height=120px alt="Unkown Person"/>
As we can see, student is of type "any". We want to infer the correct type.
But in this part, we can pass to ListComponent, a list of **any object**. And we still want the correct type to be infered.
## Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve context-outlet-type**
5. _...work On it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:4** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3Aanswer" target="_blank"><img src="https://img.shields.io/badge/-Solutions-green" alt="NgTemplateOutlet Strongly Typed"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="NgTemplateOutlet Strongly Typed solution author"/></a>
<a href="https://medium.com/@thomas.laforge/ngtemplateoutlet-type-checking-5d2dcb07a2c6" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="NgTemplateOutlet Strongly Typed blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank"><img src="./../../logo/twitter.svg" height=20px alt="Twitter"/></a>

View File

@@ -1,55 +1,13 @@
<h1>Create a component harness</h1> # Harness Creation
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
The goal of this challenge is to create a test harness for `slider.component.ts`. The harness file, `slider.harness.ts`, has already been created. ```bash
npx nx serve create-harness
The following API needs to be implemented:
```ts
async clickPlus(): Promise<void> ;
async clickMinus(): Promise<void>;
async getValue(): Promise<number> ;
async getMinValue(): Promise<number>;
async disabled(): Promise<boolean>;
async setValue(value: number): Promise<void>;
``` ```
Additionally, you should create a `HarnessPredicate` with the default predicate and the `minValue` property. ### Documentation and Instruction
```ts Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/24-harness-creation.md/).
static with<T extends MySliderHarness>(
this: ComponentHarnessConstructor<T>,
options: SliderHarnessFilters = {}
): HarnessPredicate<T>;
```
Lastly, you will need to create the test suite for `app.component`. Some default tests have already been written, but feel free to add as many tests as you want and create as many harness methods as you need.
> Angular Material documentation can be found [here](https://material.angular.io/cdk/test-harnesses/overview)
Good luck !!! 💪
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve create-harness`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:24** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="create-harness"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="create-harness solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="create-harness blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,63 +1,13 @@
<h1>CRUD application with local store</h1> # Crud application
> Author: Thomas Laforge > Author: Thomas Laforge
## Information ### Run Application
Communicating and having a global/local state in sync with your backend is the heart of any application. You will need to master those following best practises to build strong and reliable Angular Application. ```bash
npx nx serve crud
## Statement
In this exercice, you have a small CRUD application, which get a list of TODOS, update and delete some todo.
Currently we have a working exemple but filled with lots of bad practices.
### Step 1: refactor with best practices
What you will need to do:
- Avoid **any** as a type. Using Interface to leverage Typescript type system prevent errors
- Use a **separate service** for all your http calls and use a **BehaviourSubject** for your todoList
- Use **AsyncPipe** to suscribe to your todo list. _(Let you handle subscription, unsuscription and refresh of the page when data has changed)_, avoir manual subscribe when it's not needed
- Don't **mutate** data
```typescript
// Avoid this
this.todos[todoUpdated.id - 1] = todoUpdated;
// Prefer something like this, but need to be improved because we still want the same order
this.todos = [...this.todos.filter((t) => t.id !== todoUpdated.id), todoUpdated];
``` ```
- Use **ChangeDectection.OnPush** ### Documentation and Instruction
### Step 2: Improve Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/5-crud.md/).
- Add a **Delete** button: _<a href="https://jsonplaceholder.typicode.com/" target="_blank">Doc of fake API</a>_
- Handle **errors** correctly. _(Globaly)_
- Add a Global **loading** indicator. _You can use MatProgressSpinnerModule_
### Step 3: Maintainability!! add some test
- Add 2/3 tests
### Step 4: Awesomeness!!! master your state.
- Use the **component store of ngrx** as a local state of your component. _(or any other 3rd Party lib)_
- Have a **localize** Loading/Error indicator, e.g. only on the Todo being processed and **disable** all buttons of the processed Todo. _(Hint: you will need to create an ItemComponent)_
## Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve crud**
5. _...work On it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:5** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3Aanswer" target="_blank"><img src="https://img.shields.io/badge/-Solutions-green" alt="Crud solution"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Crud solution author"/></a>
<a href="https://medium.com/@thomas.laforge/discover-the-power-of-ngrx-component-store-to-create-a-local-component-state-53e3a0af7970" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="Crud blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank"><img src="./../../logo/twitter.svg" height=20px alt="Twitter"/></a>

View File

@@ -1,33 +1,13 @@
<h1>Declarative Programming to Reactive Programming</h1> # Highly Customizable CSS
> Author: Thomas Laforge > Author: Thomas Laforge
<!-- TODO: add Information/Statement/Rules/Constraint/Steps --> ### Run Application
### Information ```bash
npx nx serve declarative-to-reactive
```
### Statement ### Documentation and Instruction
### Step 1 Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/13-styling.md/).
### Step 2
### Constraints:
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve declarative-to-reactive**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:13** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="declarative to reactive"/></a>
<!-- TODO: uncomment when done late -->
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="declarative to reactive solution author"/></a>
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="declarative to reactive blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,43 +1,13 @@
<h1>decoupling component with InjectionToken</h1> # Decoupling Components
> Author: Thomas Laforge > Author: Thomas Laforge
> Big thanks to **Robin Goetz** and his [Spartan Project](https://github.com/goetzrobin/spartan). ### Run Application
> This challenge was proposed by Robin and is strongly inspired by his project.
### Information ```bash
npx nx serve decoupling
```
The goal of this challenge is to separate the behavior of a component from its style. For the purpose of this challenge, we will be working on a button element. When we click on it, we will toggle a _disabled_ property which will change the style of the element. This is quite useless in real life but the challenge aims to demonstate a useful concept. ### Documentation and Instruction
The behavior of the component (referred to as the _brain_ in the Spartan stack) is located in the brain library. The styling part (referred to as the _helmet_) is located inside the helmet library. Both libraries cannot depend on each other because we want to be able to publish them separatly. To help us address the issue, we are using the Nx enforce eslint rule. You can find more details [here](https://nx.dev/core-features/enforce-module-boundaries); Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/33-decoupling.md/).
However the button's helmet needs to access the state of the component to style the button differently based on its state. As mention above, we cannot import the `BtnDisabledDirective` directly into the helmet library as done currently. If you go to [`BtnHelmetDirective`](../../libs/decoupling/helmet/src/lib/btn-style.directive.ts), you will encounter a linting error. **A project tagged with "type:hlm" can only depend on libs tagged with "type:core"**.
### Statement
The goal of this challenge is to find a way to decouple both Directives.
### Hint
<details>
<summary>Hint 1</summary>
Carefully read the title of the challenge 😇
</details>
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx lint decoupling-helmet` to visualize the error.
5. `npx nx serve decoupling`
6. _...work on it_
7. Commit your work
8. Submit a PR with a title beginning with **Answer:33** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="decoupling"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="decoupling solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="decoupling blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,40 +1,13 @@
<h1>Dependancy Injection</h1> # Master Dependancy Injection
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
To successfully complete this challenge, you will need to have a good understanding of how Dependency Injection works inside Angular. ```bash
npx nx serve di
```
The goal is to provide the CurrencyService at the row level, so that each row displays the correct currency. Currently, the CurrencyService is only provided at the table level, which results in an error as the same currency is displayed for each row, despite each product having a different currency. ### Documentation and Instruction
One way to achieve this is by adding a second argument to the pipe, but this is not allowed. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/16-di.md/).
### Statement
- Your task is to display the correct currency for each row.
### Constraints:
- You cannot modify the pipe.
- You cannot wrap the row inside a component, as this will break the layout.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve di`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:16** that I will review and other dev can review.
<!-- TODO: add challenge number and project Name -->
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="DI"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="DI solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="DI blog article"/></a> -->
/
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,26 +1,13 @@
<h1>interoperability Rxjs and Signal</h1> # Interoperability Rxjs/Signal
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
In this challenge, we have a small reactive application using RxJS and NgRx/Component-Store. ```bash
npx nx serve interop-rxjs-signal
```
The goal of this challenge is to use the new **Signal API** introduced in Angular v16. However, we should not convert everything. Certain portions of the code are better suited for RxJS rather than Signal. It is up to you to determine the threshold and observe how **Signal and RxJS coexist**, as well as how the interoperability is achieved in Angular. ### Documentation and Instruction
### Submitting your work Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/30-interop-rxjs-signal.md/).
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve interop-rxjs-signal`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:30** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="interop-rxjs-signal"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="interop-rxjs-signal solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="interop-rxjs-signal blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,34 +1,13 @@
<h1>refactor module to standalone</h1> # Module to Standalone
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
In v14, standalone components were released and made stable in v15. If you haven't played with them, it's never too late. You can try them out in this challenge. ```bash
npx nx serve module-to-standalone
```
Moreover, the goal is to see how Nx and standalone components work together, and experience the process of decoupling your app with Nx lib and standalone components. ### Documentation and Instruction
Finally, standalone components are very simple to understand, but routing/lazy-loaded components can be a bit harder to grasp. This challenge will allow you to manipulate components at different levels of nesting and work with lazy loaded routes. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/31-module-to-standalone.md/).
After completing this challenge, standalone components will no longer hold any secrets for you.
### Statement
The goal of this challenge is to migrate your application from module based components to standalone components.
### Submitting your work
1. Fork the project
2. clone it
3. npm install
4. `npx nx serve module-to-standalone`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:31** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="module-to-standalone"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="module-to-standalone solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="module-to-standalone blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,51 +1,13 @@
<h1>Directive enhancement</h1> # Directive Enhancement
> Author: Thomas Laforge > Author: Thomas Laforge
## Information ### Run Application
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. ```bash
npx nx serve ngfor-enhancement
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 !! "_.
Currently we have :
```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>
``` ```
We want to get rid of the ng-container by writing : ### Documentation and Instruction
```typescript Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/3-directive-enhancement.md/).
<div *ngFor="let person of persons; empty: emptyList">
{{ person.name }}
</div>
<ng-template #emptyList>The list is empty !!</ng-template>
```
The goal is to **improve the ngFor directive**
## Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve ngfor-enhancement**
5. _...work On it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:3** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3Aanswer" target="_blank"><img src="https://img.shields.io/badge/-Solutions-green" alt="Directive enhancement"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Directive enhancement solution author"/></a>
<a href="https://medium.com/@thomas.laforge/ngfor-enhancement-716b44656a6c" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="Directive enhancement blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank"><img src="./../../logo/twitter.svg" height=20px alt="Twitter"/></a>

View File

@@ -1,41 +1,13 @@
<h1>NgRx Effect vs Selector</h1> # Effect vs Selector
> Author: Thomas Laforge > Author: Thomas Laforge
For this exercice, you will have a dashboard of activities displaying the name, the main teacher and a list of subtitutes. ### Run Application
## Information ```bash
npx nx serve ngrx-1
```
In NgRx, **selectors** is a very powerful tool often **misused**. You should use them as soon as you need to transform an already existing data in the store. ### Documentation and Instruction
- You shouldn't store **derived state**. This is error prone because when your data change, you will have to change it at multiple places => you should have only one place of truth with that data, and every transformation should be done in a **selector**. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/2-effect-selector.md/).
- Inside a component, you shouldn't transform a selector (using map operator), or you shouldn't have to call a selector from a function in your view. The useful data for a component should be done in a **selector**.
## Statement
##### You will have to
1. Refactor this working example of a dashboard of activities.
##### Rules:
- Only **one action** should be dispatched from a component
- Status effect is useless. Using **combineLatest** should be a red flag. And Effect are made for side effect, not transforming data. That's a selector role
- Status state might not be useful, it's only a **derived state** of existing state.
## Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve ngrx-1**
5. _...work On it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:2** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3Aanswer" target="_blank"><img src="https://img.shields.io/badge/-Solutions-green" alt="NgRx Effect vs Selector"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="NgRx Effect vs Selector solution author"/></a>
<a href="https://medium.com/@thomas.laforge/ngrx-effect-vs-reducer-vs-selector-58337ab59043" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="NgRx Effect vs Selector blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,44 +1,13 @@
<h1>Ngrx Notification</h1> # Power of Effect
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
NgRx Effect is a very powerful library develop by the NgRx team. Effects subscribe to a HOT Observable and listen to any event dispatch from any place inside the application. ```bash
npx nx serve ngrx-notification
```
But what we often forget is that Effects can subscribe to ANY observables. Which means we can wrap a hot observable inside an effect and had logic in it. ### Documentation and Instruction
In this exercice, we will find a way to create a very powerful, scalable and maintanable push messages listener. Currently, the code is located inside a single file with a if else condition to send the push data to the right location. This code is not very scalable since we need to add more and more else, and so not very maintanable since the piece of code will become bigger and bigger. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/7-power-effect.md/).
Also, we load the whole file at startup even if we haven't load some part of the application (lazy loading); and so we don't need to listen or update that part of the store. We need to decouple that logic.
### Step 1
create an injection token to hide the push service implementation.
### Step 2
create one ngrx effect, or component store effect for each push type, and implement your logic
### Step 3
load your effect only when necessary.
the application contain a root route, a lazy loaded route and a component with a local state (implemented with Component store)
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve ngrx-notification**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:7** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A7+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="Ngrx notification"/></a>
<!-- TODO: uncomment when done late -->
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="{Project name} solution author"/></a>
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="{Project name} blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,33 +1,13 @@
<h1>Function overload</h1> # Function Overload
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
Angular uses TypeScript, and mastering TypeScript can help you avoid runtime errors by catching them at compile time. ```bash
npx nx serve overload`
```
In this challenge, we have a function to create a vehicle. However, each vehicle type requires different mandatory properties. ### Documentation and Instruction
Currently, we are getting an error at runtime if one property is missing and we don't get the return Type, which is not ideal.
One solution would be to create a separate function for each vehicle type, but for this challenge, I want to use the same function and have TypeScript automatically complete the properties depending on the type passed as the first parameter.
To achieve this, we will use overload functions. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/typescript/15-overload-fn.md/).
### Statement
- Use function overload
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **`npx nx serve overload`**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:15** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="overload"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="overload solution author"/></a>
<a href="https://medium.com/ngconf/function-overloading-in-typescript-8236706b2c05" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="overload blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,58 +1,13 @@
<h1>OnPush to optimize Change Detection</h1> # Default vs OnPush
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
In this series of challenges, you will learn how to optimize and enhance the performance of your Angular Application. ```bash
npx nx serve performance-default-onpush
```
The first step is to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so. This extension allows you to profile your application and detect performance issues. ### Documentation and Instruction
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`. To provide a clearer demonstration, I have added color enlightment to each component and each row in our application. However, in real-world scenarios, you will not have such visualization. This is where the Angular DevTool profiler comes to the rescue. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular-performance/34-default-onpush.md/).
Start by serving this application by running: `npx nx serve performance-default-onpush` inside your terminal. Then open Chrome DevTool by pressing **F12** and switch to the Angular Tab. From there you can select the Profiler tab as shown below.
![profiler tab](./img/profiler-tab.png 'Profiler tab')
Start profiling your application and type some letters inside the input field. You will notice that each element of your application will flash at each change detection cycle and the profiler will show you a bar for each change detection cycle.
If you click on one of the bars (indicated by the yellow arrow on the picture below), you can see that `PersonListComponent`, `RandomComponent` and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
![profiler record](./img/profiler-record.png 'Profiler Record')
### Statement
The goal of this challenge is to improve the clustering of change detection within the application.
### Hints:
<details>
<summary>Hint 1</summary>
Use `ChangeDetectionStrategy.OnPush` but this will not be enough.
</details>
<details>
<summary>Hint 2</summary>
Create smaller components to better separate the input field from the list.
</details>
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve performance-default-onpush`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:34** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="performance-default-onpush"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="performance-default-onpush solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="performance-default-onpush blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,65 +1,13 @@
<h1>Permissions</h1> # Structural Directive
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
Structural directive is an important concept you will need to master to improve your angular skills and knowledge. This will be the first part of this challenge. ```bash
npx nx serve permissions
Guard is also very important since you will always need it in every application you build.
### Statement
In LoginComponent, you will find 6 buttons corresponding at 6 differents users.
- Admin
- Manager
- Reader
- Writer
- Reader and Writer
- Client
- Everyone
### Step 1
In **InformationComponent**, display the correct piece of information for each roles.
#### Constraints:
- no ngIf directive inside **InformationComponent**
- importing the store inside **InformationComponent** is not allowed.
You should end up with something like below:
```html
<div *hasRole="Role1">Info for Role1</div>
``` ```
```html ### Documentation and Instruction
<div *hasRole="['Role1', 'Role2']">Info for Role1 and Role2</div>
```
```html Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/6-permissions.md/).
<div *hasRoleSuperAdmin="true">Info Only for superadmin</div>
```
### Step 2
In **Routes.ts**, route all user to the correct **DashboardComponent** using **CanMatch** guard.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve permissions**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:6** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="permissions"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="permissions solution author"/></a>
<a href="https://medium.com/@thomas.laforge/create-a-custom-structural-directive-to-manage-permissions-like-a-pro-11a1acad30ad" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation: part 1 directives-blue" alt="permissions directive blog article"/></a>
<a href="https://medium.com/@thomas.laforge/create-a-route-guard-to-manage-permissions-26f16cc9a1ca" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation: part 2 guards-blue" alt="permissions guard blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,31 +1,13 @@
<h1>Simple Pure pipe</h1> # Pure Pipe
> Author: Thomas Laforge > Author: Thomas Laforge
The goal of this serie of 3 pipe challenges is to master PIPES in Angular. ### Run Application
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed. ```bash
npx nx serve pipe-easy
```
### Information: ### Documentation and Instruction
In this first exercice, you add calling a simple function inside your template. The goal is to convert it to a pipe. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/8-pipe-pure.md/).
### Constraints:
- must be strongly typed
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve pipe-easy`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:8** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="Pure simple pipe"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Pure simple pipe solution author"/></a>
<a href="https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="Pure simple pipe blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,32 +1,13 @@
<h1>Strongly typed pipe</h1> # Utility Wrapper Pipe
> Author: Thomas Laforge > Author: Thomas Laforge
The goal of this serie of 3 pipe challenges is to master PIPES in Angular. ### Run Application
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed. ```bash
npx nx serve pipe-hard
```
### Information: ### Documentation and Instruction
In this third exercice, you want to access utils functions. Currently we 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. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/10-pipe-utility.md/).
### Constraints:
- must be strongly typed
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve pipe-hard`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:10** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="Strongly Typed pipe"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Strongly Typed pipe solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="Strongly Typed pipe blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,32 +1,13 @@
<h1>WrapFn pipe</h1> # Wrap Function Pipe
> Author: Thomas Laforge > Author: Thomas Laforge
The goal of this serie of 3 pipe challenges is to master PIPES in Angular. ### Run Application
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed. ```bash
npx nx serve pipe-intermediate
```
### Information: ### Documentation and Instruction
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. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/9-pipe-wrapFn.md/).
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
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve pipe-intermediate`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:9** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="WrapFn pipe"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="WrapFn pipe solution author"/></a>
<a href="https://medium.com/ngconf/boost-your-apps-performance-by-wrapping-your-functions-inside-a-pipe-7e889a901d1d" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="WrapFn pipe blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,23 +1,13 @@
<h1>Router Input</h1> # @RouterInput()
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement ### Run Application
In this small application, you can pass data though routing to `TestComponent`. v16 of Angular introduiced `RouterInput`. The goal of this exercice is to refactor the code to use the new `RouterInput` strategy. ```bash
npx nx serve router-input
```
### Submitting your work ### Documentation and Instruction
1. Fork the project Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/22-router-input.md/).
2. clone it
3. npm ci
4. `npx nx serve router-input`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:22** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="router-input"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="router-input solution author"/></a>
<a href="https://medium.com/ngconf/accessing-route-params-in-angular-1f8e12770617" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="router-input blog article"/></a>
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,41 +1,13 @@
<h1>BUG: RxJs chaining operators</h1> # High Order Operator Bug
> Author: Thomas Laforge > Author: Thomas Laforge
Let's dive inside the wonderful word of RxJs. ### Run Application
This challenge is inspired by a real-life example. ```bash
npx nx serve rxjs-pipe-bug
```
### Presentation of the challenge ### Documentation and Instruction
#### User Story Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/11-bug-chaining-operator.md/).
We need a button for each `Topic`. When we click on it, we delete all objects with this `Topic` in our database _(Fake DB in our case)_. Finally we display **All [topic] have been deleted** is everything was deleted successfully or **Error: deletion of some [topic] failed** if some deletions failed
#### Constraints:
We can only pass one object to our DB for deletion at the time. The DB will respond true if the data was successfully deleted and false otherwise.
### What you need to do
The QA team reports a **bug**. The UI shows **All [topic] have been deleted** all the time, even if some deletions fail.
👉 Spot the bug and correct it.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve rxjs-pipe-bug`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:11** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="Rxjs pipe bug"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Rxjs pipe bug solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="{Project name} blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,41 +1,13 @@
<h1>RxJs race condition</h1> # Race Condition
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
The goal of this application is to display a list of topics in a modal when a button is clicked. The application functions correctly. However, your tech lead has asked you to add tests and they are failing. ```bash
npx nx serve rxjs-race-condition
```
### Statement ### Documentation and Instruction
Correct your application to pass the test Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/14-race-condition.md/).
### Constraints:
- I can see you coming 🤣 => You CANNOT change the test (Test is working fine) 😳
- You CANNOT change the `fakeGetHttpTopic` method. A delay has been added to fake a slow network.
### Run the test
HEADLESS : `npx nx component-test rxjs-race-condition`
WATCH MODE : `npx nx component-test rxjs-race-condition --watch`
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve rxjs-race-condition`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:14** that I will review and other dev can review.
<!-- TODO: add challenge number and project Name -->
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="RxJs race condition"/></a>
<!-- TODO: uncomment when done late -->
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="RxJs race condition solution author"/></a>
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="RxJs race condition blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,42 +1,13 @@
<h1>Mastering Change Detection cycle with a scroll example</h1> # Optimize Change Detection
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
In this challenge, you will need to optimize the change detection cycles run by Angular. ```bash
npx nx serve scroll-cd
```
Zone.js triggers a change detection cycle each time a scroll event is dispatched. However we only want to show or hide a button at a specific scroll position. Therefore, we only want to refresh our application once. ### Documentation and Instruction
> You can vizualise how many times CD is triggered by installing the [Angular chrome devTool](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) and starting a new recording on the profiler tab. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular-performance/12-scroll-cd.md/).
The following video will explain what is the goal of this challenge.
<video controls src="https://user-images.githubusercontent.com/30832608/209819211-58d9ddcf-e1ad-4a78-8a7a-2be9d729e3f1.mov">
</video>
### Statement
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a CD only when needed.
#### Constraint:
You cannot opt-out of zone.js. If this code is part of a large project and you opt out of zone.js, you will break many things within your application.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve scroll-cd**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:12** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A12+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="Mastering Change Detection cycle with a scroll example"/></a>
<!-- TODO: uncomment when done late -->
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Mastering Change Detection cycle with a scroll example solution author"/></a>
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="Mastering Change Detection cycle with a scroll example, blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,32 +1,13 @@
<h1>Customizable style</h1> # Highly Customizable CSS
> Author: Thomas Laforge > Author: Thomas Laforge
Styling is an important part of a day job of a frontend developer often underestimated. In Angular application, I often see people use `@Input()` to customize the style of their component. But `@Input()` should be used only for the logic and we should use other technique for styling. We can take advantage of css variable and host-context. ### Run Application
In this challenge, you will need to use both to delete all `@Input()` from your code. ```bash
npx nx serve styling
```
Styling is an important aspect of a frontend developer's day job, but it is often underestimated. In Angular applications, I frequently see people using `@Input()` to customize the style of their components. However, `@Input()` should only be used for logic; and other techniques, such as CSS variables and host-context, should be used for styling. ### Documentation and Instruction
In this challenge, you will need to use both CSS variables and :host-context to remove all `@Input()` from your code. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/13-styling.md/).
### Constraints:
- In your final submission, your component should not contain any lines of code. All styling should be handled within the decorator _(or external css files if you prefer)_
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. **nx serve styling**
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:13** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="styling"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="styling solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="styling blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,32 +1,13 @@
<h1>Test of a simple checkbox</h1> # Checkbox
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
This is the perfect example to get started with `Testing Library`. ```bash
npx nx serve testing-checkbox
```
You will need to only check if the button gets enabled when clicking on the checkbox ### Documentation and Instruction
You can look into debug function to get full power of `Testing Library` like: Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/28-checkbox.md/).
- logRoles(...);
- screen.debug(); // you can pass a element as input
- screen.logTestingPlaygroundURL(); // you can pass a element as input
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-checkbox`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:28** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="testing-checkbox"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="testing-checkbox solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="testing-checkbox blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,32 +1,13 @@
<h1>Testing with Angular CDK Harness</h1> # Harness
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement: ### Run Application
The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses. ```bash
npx nx serve testing-harness
```
The goal is to test the functionality of `child.component.ts`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well. ### Documentation and Instruction
**Note:** You are welcome to use Testing Library if you wish. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/23-harness.md/).
Documentation for CDK Component Harness is [here](https://material.angular.io/cdk/test-harnesses/overview#api-for-test-authors)
Documentation for Angular Material component is [here](https://material.angular.io/components/button/overview)
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-harness` to play with the application
5. `npx nx test testing-harness` to test your application with Testing Library
6. _...work on it_
7. Commit your work
8. Submit a PR with a title beginning with **Answer:23** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="harness testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="harness testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="nested testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,35 +1,13 @@
<h1>Input / Output testing</h1> # Input Output
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement: ### Run Application
We have a small counter application that increment or decrement a number. ```bash
You can play with it by running : `npx nx serve testing-input-output`. npx nx serve testing-input-output
```
The goal is to test `CounterComponent` with Testing library and Cypress ### Documentation and Instruction
The file named `counter.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/19-input-output.md/).
For testing cypress, you will execute your test inside the `counter.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-input-output` to play with the application
5. `npx nx test testing-input-output` to test your application with Testing Library
6. `npx nx component-test testing-input-output --watch` to test your application with Cypress
7. _...work on it_
8. Commit your work
9. Submit a PR with a title beginning with **Answer:19** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="input output testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="input output testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="input output testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,38 +1,13 @@
<h1>Modal testing</h1> # Modal
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement: ### Run Application
The goal of this challenge is to test dialogs inside your application. ```bash
Within this program, you will get an error modal if the user doesn't input a name, while a confirmation modal will appear in all other cases. npx nx serve testing-modal
In the confirmation modal, if you click the "confirm" button, a message confirming the submission of the form will appear. Otherwise, if the user clicks on "Cancel", an error message will be displayed. ```
You can play with it by running : `npx nx serve testing-modal`. ### Documentation and Instruction
The goal is to test this behavior with Testing library and Cypress Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/20-modal.md/).
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-modal`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-modal` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-modal` to play with the application
5. `npx nx test testing-modal` to test your application with Testing Library
6. `npx nx component-test testing-modal --watch` to test your application with Cypress
7. _...work on it_
8. Commit your work
9. Submit a PR with a title beginning with **Answer:20** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="modal testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="modal testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="nested testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,36 +1,13 @@
<h1>Nested component testing</h1> # Nested Components
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement: ### Run Application
We have a small application that send a title to a fake backend that you type inside a input. ```bash
If the title is correctly typed, you can send the request otherwise you get a nice error and the request is not sent. npx nx serve testing-nested
You can play with it by running : `npx nx serve testing-nested`. ```
The goal is to test this behavior with Testing library and Cypress ### Documentation and Instruction
The file named `child.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/18-nested-comp.md/).
For testing cypress, you will execute your test inside the `child.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-nested` to play with the application
5. `npx nx test testing-nested` to test your application with Testing Library
6. `npx nx component-test testing-nested --watch` to test your application with Cypress
7. _...work on it_
8. Commit your work
9. Submit a PR with a title beginning with **Answer:18** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="nested testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="nested testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="nested testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,42 +1,13 @@
<h1>Router Testing</h1> # Router
> Author: Thomas Laforge > Author: Thomas Laforge
### Information ### Run Application
Testing is a crucial step in building scalable, maintainable, and trustworthy applications. ```bash
Testing should never be avoided, even in the face of short deadlines or strong pressure from the product team. npx nx serve testing-router-outlet
Nowadays, there are numerous awesome tools available that make it easy to test your code and provide a great developer experience. ```
In this series of testing exercises, we will learn and master [Testing Library](https://testing-library.com/docs/) and [Cypress Component Testing](https://docs.cypress.io/guides/component-testing/angular/overview) that simplifies DOM manipulation for testing any Angular component. ### Documentation and Instruction
### Statement: Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/17-router.md/).
We have a functional application that lists available books for borrowing inside a library. If the book you searched is available, you will be directed to the corresponding book(s), otherwise, you will end up on an error page.
The goal is to test this behavior with Testing library and Cypress
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-router-outlet`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-router-outlet` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-router-outlet` to play with the application
5. `npx nx test testing-router-outlet` to test your application with Testing Library
6. `npx nx component-test testing-router-outlet --watch` to test your application with Cypress
7. _...work on it_
8. Commit your work
9. Submit a PR with a title beginning with **Answer:17** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="router testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="router testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="router testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -1,33 +1,13 @@
<h1>Todo list app testing</h1> # Real-life Application
> Author: Thomas Laforge > Author: Thomas Laforge
### Statement: ### Run Application
I built this more real life application to create more real life test cases. ```bash
In this application, you can search for tickets, you can assign or finish them. You can also create new tickets. npx nx serve testing-todos-list
```
This is a very simple application, but it will let you deal with asynchronous task and mocks ### Documentation and Instruction
The goal of this challenge is to write all test cases of `ticket.store` , `list.component` and `row.component` with Testing Library. Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/29-real-application.md/).
You can also do it with cypress.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. `npx nx serve testing-todos-list` to play with the application
5. `npx nx test testing-todos-list` to test your application with Testing Library
6. `npx nx component-test testing-todos-list --watch` to test your application with Cypress
7. _...work on it_
8. Commit your work
9. Submit a PR with a title beginning with **Answer:29** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="todo list app testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A285+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="todo list app testing solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="nested testing blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -4,5 +4,51 @@ description: Challenge 12 about optimizing the number of change detection cycle
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/scroll-cd/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #12</div>
### Information
In this challenge, you will need to optimize the change detection cycles run by Angular.
Zone.js triggers a change detection cycle each time a scroll event is dispatched. However we only want to show or hide a button at a specific scroll position. Therefore, we only want to refresh our application once.
> You can vizualise how many times CD is triggered by installing the [Angular chrome devTool](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) and starting a new recording on the profiler tab.
The following video will explain what is the goal of this challenge.
<video controls src="https://user-images.githubusercontent.com/30832608/209819211-58d9ddcf-e1ad-4a78-8a7a-2be9d729e3f1.mov">
</video>
### Statement
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a CD only when needed.
#### Constraint:
You cannot opt-out of zone.js. If this code is part of a large project and you opt out of zone.js, you will break many things within your application.
---
:::note
Start the project by running: `npx nx serve scroll-cd`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:12</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A12+label%3Aanswer"
alt="Optimize Change Detection community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A'
alt="Optimize Change Detection solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,55 @@ description: Challenge 32 is about debugging an application that has issue when
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/bug-cd/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #32</div>
This challenge is inspired by a real-life example that I simplified to create this nice challenge.
### Information
In this small application, we have a navigation menu to route our application to either `barComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console.
### Statement
The goal of the challenge is to debug this application and make it work.
#### Hints
<details>
<summary>Hint 1</summary>
If you comment out `routerLinkActive="isSelected"` inside `NavigationComponent`: the application loads correctly.
</details>
<details>
<summary>Hint 2</summary>
If you open the [`RouterLinkActive` source code](https://github.com/angular/angular/blob/main/packages/router/src/directives/router_link_active.ts) and go to **line 196**, Angular is calling `this.cdr.markForCheck` inside a microTask which triggers a new CD cycle. If you comment out this line, the application loads again, however the bug is not inside the Angular Framework. 😅😯
</details>
---
:::note
Start the project by running: `npx nx serve bug-cd`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:32</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3Aanswer"
alt="Change Detection Bug community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3A'
alt="Change Detection Bug solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,68 @@ description: Challenge 34 is about learning the difference between Default and O
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/performance/default-onpush/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #34</div>
### Information
In this series of challenges, you will learn how to optimize and enhance the performance of your Angular Application.
The first step is to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so. This extension allows you to profile your application and detect performance issues.
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`. To provide a clearer demonstration, I have added color enlightment to each component and each row in our application. However, in real-world scenarios, you will not have such visualization. This is where the Angular DevTool profiler comes to the rescue.
Start by serving this application by running: `npx nx serve performance-default-onpush` inside your terminal. Then open Chrome DevTool by pressing **F12** and switch to the Angular Tab. From there you can select the Profiler tab as shown below.
![profiler tab](./img/profiler-tab.png 'Profiler tab')
Start profiling your application and type some letters inside the input field. You will notice that each element of your application will flash at each change detection cycle and the profiler will show you a bar for each change detection cycle.
If you click on one of the bars (indicated by the yellow arrow on the picture below), you can see that `PersonListComponent`, `RandomComponent` and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
![profiler record](./img/profiler-record.png 'Profiler Record')
### Statement
The goal of this challenge is to improve the clustering of change detection within the application.
### Hints:
<details>
<summary>Hint 1</summary>
Use `ChangeDetectionStrategy.OnPush` but this will not be enough.
</details>
<details>
<summary>Hint 2</summary>
Create smaller components to better separate the input field from the list.
</details>
---
:::note
Start the project by running: `npx nx serve performance-default-onpush`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:34</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3Aanswer"
alt="Default vs OnPush community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3A'
alt="Default vs OnPush solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,42 @@ description: Challenge 10 is about creating a pipe to wrap utilities
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/pipe-hard/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #10</div>
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
### Information:
In this third exercice, you want to access utils functions. Currently we 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
---
:::note
Start the project by running: `npx nx serve pipe-hard`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:10</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3Aanswer"
alt="Utility Wrapper Pipe community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3A'
alt="Utility Wrapper Pipe solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,42 @@ description: Challenge 13 is about creating highly customizable CSS styles
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/styling/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #13</div>
Styling is an important part of a day job of a frontend developer often underestimated. In Angular application, I often see people use `@Input()` to customize the style of their component. But `@Input()` should be used only for the logic and we should use other technique for styling. We can take advantage of css variable and host-context.
In this challenge, you will need to use both to delete all `@Input()` from your code.
Styling is an important aspect of a frontend developer's day job, but it is often underestimated. In Angular applications, I frequently see people using `@Input()` to customize the style of their components. However, `@Input()` should only be used for logic; and other techniques, such as CSS variables and host-context, should be used for styling.
In this challenge, you will need to use both CSS variables and :host-context to remove all `@Input()` from your code.
### Constraints:
- In your final submission, your component should not contain any lines of code. All styling should be handled within the decorator _(or external css files if you prefer)_
---
:::note
Start the project by running: `npx nx serve styling`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:13</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3Aanswer"
alt="Highly Customizable CSS community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A'
alt="Highly Customizable CSS solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,47 @@ description: Challenge 16 is about masjering how dependancy injection works
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/di/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #16</div>
### Information
To successfully complete this challenge, you will need to have a good understanding of how Dependency Injection works inside Angular.
The goal is to provide the CurrencyService at the row level, so that each row displays the correct currency. Currently, the CurrencyService is only provided at the table level, which results in an error as the same currency is displayed for each row, despite each product having a different currency.
One way to achieve this is by adding a second argument to the pipe, but this is not allowed.
### Statement
- Your task is to display the correct currency for each row.
### Constraints:
- You cannot modify the pipe.
- You cannot wrap the row inside a component, as this will break the layout.
---
:::note
Start the project by running: `npx nx serve di`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:16</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3Aanswer"
alt="Master Dependancy Injection community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3A'
alt="Master Dependancy Injection solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,39 @@ description: Challenge 21 is about navigating inside the page with anchor
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/anchor-scrolling/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #21</div>
### Information
You begin with an application that has basic navigation and anchor navigation in the `HomeComponent`. However, using `href` recreates the path each time and refreshes the page.
### Statement
- Your task is to refactor this application to use the built-in navigation tool to better fit within the Angular Framework. You can explore the router, but it's better to stay within the template and use the `RouterLink` directive.
- To improve the user experience, add smooth scrolling.
---
:::note
Start the project by running: `npx nx serve anchor-scrolling`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:21</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3Aanswer"
alt="Anchor Navigation community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3A'
alt="Anchor Navigation solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,42 @@ description: Challenge 22 is about using the @Input decorator to retreive router
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/router-input/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #22</div>
### Statement
In this small application, you can pass data though routing to `TestComponent`. v16 of Angular introduiced `RouterInput`. The goal of this exercice is to refactor the code to use the new `RouterInput` strategy.
---
:::note
Start the project by running: `npx nx serve router-input`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:22</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3Aanswer"
alt="@RouterInput() community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3A'
alt="@RouterInput() solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/ngconf/accessing-route-params-in-angular-1f8e12770617'
target="_blank"
rel="noopener noreferrer"
alt="@RouterInput() blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,16 +4,42 @@ description: Challenge 3 is about enhancing a built-in directive
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/ngfor-enhancement/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #3</div> <div class="chip">Challenge #3</div>
## 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.
But the real power is that you can enhance an already existing directive which moreover doesn't **belong** to you.
## Statement ## Statement
## Constraints 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 :
```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>
```
We want to get rid of the ng-container by writing :
```typescript
<div *ngFor="let person of persons; empty: emptyList">
{{ person.name }}
</div>
<ng-template #emptyList>The list is empty !!</ng-template>
```
The goal is to **improve the ngFor directive**
--- ---
@@ -27,20 +53,20 @@ Your PR title must start with <b>Answer:3</b>.
<div class="article-footer"> <div class="article-footer">
<a <a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A1+label%3Aanswer" href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3Aanswer"
alt="Directive enhancement community solutions"> alt="Directive Enhancement community solutions">
❖ Community Answers ❖ Community Answers
</a> </a>
<a <a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A1+label%3A"answer+author"' href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3A'
alt="Directive enhancement solution author"> alt="Directive Enhancement solution author">
▶︎ Author Answer ▶︎ Author Answer
</a> </a>
<a <a
href="https://medium.com/@thomas.laforge/ngfor-enhancement-cc3a9805e4c5" href='https://medium.com/@thomas.laforge/ngfor-enhancement-716b44656a6c'
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
alt="Directive enhancement blog article"> alt="Directive Enhancement blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg> <svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post Blog Post
</a> </a>

View File

@@ -4,5 +4,36 @@ description: Challenge 30 is about learning how to mix signal with Rxjs
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/interop-rxjs-signal/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #30</div>
### Information
In this challenge, we have a small reactive application using RxJS and NgRx/Component-Store.
The goal of this challenge is to use the new **Signal API** introduced in Angular v16. However, we should not convert everything. Certain portions of the code are better suited for RxJS rather than Signal. It is up to you to determine the threshold and observe how **Signal and RxJS coexist**, as well as how the interoperability is achieved in Angular.
---
:::note
Start the project by running: `npx nx serve interop-rxjs-signal`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:30</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3Aanswer"
alt="Interoperability Rxjs/Signal community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3A'
alt="Interoperability Rxjs/Signal solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,44 @@ description: Challenge 31 is about migrating a module based application to a sta
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/module-to-standalone/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #31</div>
### Information
In v14, standalone components were released and made stable in v15. If you haven't played with them, it's never too late. You can try them out in this challenge.
Moreover, the goal is to see how Nx and standalone components work together, and experience the process of decoupling your app with Nx lib and standalone components.
Finally, standalone components are very simple to understand, but routing/lazy-loaded components can be a bit harder to grasp. This challenge will allow you to manipulate components at different levels of nesting and work with lazy loaded routes.
After completing this challenge, standalone components will no longer hold any secrets for you.
### Statement
The goal of this challenge is to migrate your application from module based components to standalone components.
---
:::note
Start the project by running: `npx nx serve module-to-standalone`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:31</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3Aanswer"
alt="Module to Standalone community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3A'
alt="Module to Standalone solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,52 @@ description: Challenge 33 is about decoupling two strongly coupled components us
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/decoupling/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #33</div>
> Big thanks to **Robin Goetz** and his [Spartan Project](https://github.com/goetzrobin/spartan).
> This challenge was proposed by Robin and is strongly inspired by his project.
### Information
The goal of this challenge is to separate the behavior of a component from its style. For the purpose of this challenge, we will be working on a button element. When we click on it, we will toggle a _disabled_ property which will change the style of the element. This is quite useless in real life but the challenge aims to demonstate a useful concept.
The behavior of the component (referred to as the _brain_ in the Spartan stack) is located in the brain library. The styling part (referred to as the _helmet_) is located inside the helmet library. Both libraries cannot depend on each other because we want to be able to publish them separatly. To help us address the issue, we are using the Nx enforce eslint rule. You can find more details [here](https://nx.dev/core-features/enforce-module-boundaries);
However the button's helmet needs to access the state of the component to style the button differently based on its state. As mention above, we cannot import the `BtnDisabledDirective` directly into the helmet library as done currently. If you go to [`BtnHelmetDirective`](../../libs/decoupling/helmet/src/lib/btn-style.directive.ts), you will encounter a linting error. **A project tagged with "type:hlm" can only depend on libs tagged with "type:core"**.
### Statement
The goal of this challenge is to find a way to decouple both Directives.
### Hint
<details>
<summary>Hint 1</summary>
Carefully read the title of the challenge 😇
</details>
---
:::note
Start the project by running: `npx nx serve decoupling`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:33</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3Aanswer"
alt="Decoupling Components community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3A'
alt="Decoupling Components solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,68 @@ description: Challenge 4 is about strongly typing ngContextOutlet directives
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/context-outlet-type/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #4</div>
## Information
Angular offer the static function **ngTemplateContextGuard** to strongly type structural directive.
However the context of **NgTemplateOutlet** type is **Object**. But which the help of the above guard, we can improve that behavior.
## Statement
In this exercice, we want to learn how to strongly typed our ng-template in our AppComponent.
This exercice has two level of complexity.
### Level 1: known Interface
Currently we have the following piece of code.
<img src="./img/unknown-person.png" height=120px alt="Unkown Person"/>
As we can see, name is of type "any". We want to infer the correct type.
### Level 2: generic Interface
Currently we have the following piece of code.
<img src="./img/unknown-student.png" height=120px alt="Unkown Person"/>
As we can see, student is of type "any". We want to infer the correct type.
But in this part, we can pass to ListComponent, a list of **any object**. And we still want the correct type to be infered.
---
:::note
Start the project by running: `npx nx serve context-outlet-type`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:4</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3Aanswer"
alt="Typed ContextOutlet community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3A'
alt="Typed ContextOutlet solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/@thomas.laforge/ngtemplateoutlet-type-checking-5d2dcb07a2c6'
target="_blank"
rel="noopener noreferrer"
alt="Typed ContextOutlet blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,5 +4,74 @@ description: Challenge 5 is about refactoring a crud application
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/crud/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #5</div>
## Information
Communicating and having a global/local state in sync with your backend is the heart of any application. You will need to master those following best practises to build strong and reliable Angular Application.
## Statement
In this exercice, you have a small CRUD application, which get a list of TODOS, update and delete some todo.
Currently we have a working exemple but filled with lots of bad practices.
### Step 1: refactor with best practices
What you will need to do:
- Avoid **any** as a type. Using Interface to leverage Typescript type system prevent errors
- Use a **separate service** for all your http calls and use a **BehaviourSubject** for your todoList
- Use **AsyncPipe** to suscribe to your todo list. _(Let you handle subscription, unsuscription and refresh of the page when data has changed)_, avoir manual subscribe when it's not needed
- Don't **mutate** data
```typescript
// Avoid this
this.todos[todoUpdated.id - 1] = todoUpdated;
// Prefer something like this, but need to be improved because we still want the same order
this.todos = [...this.todos.filter((t) => t.id !== todoUpdated.id), todoUpdated];
```
- Use **ChangeDectection.OnPush**
### Step 2: Improve
- Add a **Delete** button: _<a href="https://jsonplaceholder.typicode.com/" target="_blank">Doc of fake API</a>_
- Handle **errors** correctly. _(Globaly)_
- Add a Global **loading** indicator. _You can use MatProgressSpinnerModule_
### Step 3: Maintainability!! add some test
- Add 2/3 tests
### Step 4: Awesomeness!!! master your state.
- Use the **component store of ngrx** as a local state of your component. _(or any other 3rd Party lib)_
- Have a **localize** Loading/Error indicator, e.g. only on the Todo being processed and **disable** all buttons of the processed Todo. _(Hint: you will need to create an ItemComponent)_
---
:::note
Start the project by running: `npx nx serve crud`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:5</b>.
:::
<div class="article-footer">
<a
href="https://jsonplaceholder.typicode.com/"
alt="Crud application community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3Aanswer'
alt="Crud application solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,83 @@ description: Challenge 6 is about creating a structural directive to handle perm
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/permissions/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #6</div>
### Information
Structural directive is an important concept you will need to master to improve your angular skills and knowledge. This will be the first part of this challenge.
Guard is also very important since you will always need it in every application you build.
### Statement
In LoginComponent, you will find 6 buttons corresponding at 6 differents users.
- Admin
- Manager
- Reader
- Writer
- Reader and Writer
- Client
- Everyone
### Step 1
In **InformationComponent**, display the correct piece of information for each roles.
#### Constraints:
- no ngIf directive inside **InformationComponent**
- importing the store inside **InformationComponent** is not allowed.
You should end up with something like below:
```html
<div *hasRole="Role1">Info for Role1</div>
```
```html
<div *hasRole="['Role1', 'Role2']">Info for Role1 and Role2</div>
```
```html
<div *hasRoleSuperAdmin="true">Info Only for superadmin</div>
```
### Step 2
In **Routes.ts**, route all user to the correct **DashboardComponent** using **CanMatch** guard.
---
:::note
Start the project by running: `npx nx serve permissions`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:6</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3Aanswer"
alt="Structural Directive community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3A'
alt="Structural Directive solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/@thomas.laforge/create-a-custom-structural-directive-to-manage-permissions-like-a-pro-11a1acad30ad'
target="_blank"
rel="noopener noreferrer"
alt="Structural Directive blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,5 +4,50 @@ description: Challenge 8 is about creating a pure pipe
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/pipe-easy/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #8</div>
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
### Information:
In this first exercice, you add calling a simple function inside your template. The goal is to convert it to a pipe.
### Constraints:
- must be strongly typed
---
:::note
Start the project by running: `npx nx serve pipe-easy`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:8</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3Aanswer"
alt="Pure Pipe community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3A'
alt="Pure Pipe solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d'
target="_blank"
rel="noopener noreferrer"
alt="Pure Pipe blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,5 +4,51 @@ description: Challenge 9 is about creating a pipe to wrap component fonctions
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/pipe-intermediate/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #9</div>
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
### 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.
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
---
:::note
Start the project by running: `npx nx serve pipe-intermediate`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:9</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3Aanswer"
alt="Wrap Function Pipe community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3A'
alt="Wrap Function Pipe solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/ngconf/boost-your-apps-performance-by-wrapping-your-functions-inside-a-pipe-7e889a901d1d'
target="_blank"
rel="noopener noreferrer"
alt="Wrap Function Pipe blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,5 +4,60 @@ description: Challenge 2 is about learning the difference between effects and se
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/ngrx-1/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #2</div>
For this exercice, you will have a dashboard of activities displaying the name, the main teacher and a list of subtitutes.
## Information
In NgRx, **selectors** is a very powerful tool often **misused**. You should use them as soon as you need to transform an already existing data in the store.
- You shouldn't store **derived state**. This is error prone because when your data change, you will have to change it at multiple places => you should have only one place of truth with that data, and every transformation should be done in a **selector**.
- Inside a component, you shouldn't transform a selector (using map operator), or you shouldn't have to call a selector from a function in your view. The useful data for a component should be done in a **selector**.
## Statement
##### You will have to
1. Refactor this working example of a dashboard of activities.
##### Rules:
- Only **one action** should be dispatched from a component
- Status effect is useless. Using **combineLatest** should be a red flag. And Effect are made for side effect, not transforming data. That's a selector role
- Status state might not be useful, it's only a **derived state** of existing state.
---
:::note
Start the project by running: `npx nx serve ngrx-1`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:2</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3Aanswer"
alt="Effect vs Selector community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3A'
alt="Effect vs Selector solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/@thomas.laforge/ngrx-effect-vs-reducer-vs-selector-58337ab59043'
target="_blank"
rel="noopener noreferrer"
alt="Effect vs Selector blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>

View File

@@ -4,5 +4,53 @@ description: Challenge 7 is about creating an Ngrx effect with another Rxjs Hot
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/ngrx-notification/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #7</div>
### Information
NgRx Effect is a very powerful library develop by the NgRx team. Effects subscribe to a HOT Observable and listen to any event dispatch from any place inside the application.
But what we often forget is that Effects can subscribe to ANY observables. Which means we can wrap a hot observable inside an effect and had logic in it.
In this exercice, we will find a way to create a very powerful, scalable and maintanable push messages listener. Currently, the code is located inside a single file with a if else condition to send the push data to the right location. This code is not very scalable since we need to add more and more else, and so not very maintanable since the piece of code will become bigger and bigger.
Also, we load the whole file at startup even if we haven't load some part of the application (lazy loading); and so we don't need to listen or update that part of the store. We need to decouple that logic.
### Step 1
create an injection token to hide the push service implementation.
### Step 2
create one ngrx effect, or component store effect for each push type, and implement your logic
### Step 3
load your effect only when necessary.
the application contain a root route, a lazy loaded route and a component with a local state (implemented with Component store)
---
:::note
Start the project by running: `npx nx serve ngrx-notification`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:7</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A7+label%3Aanswer"
alt="Power of Effect community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A'
alt="Power of Effect solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,50 @@ description: Challenge 11 is about resolving a Rxjs bug because of high order op
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/rxjs-pipe-bug/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #11</div>
Let's dive inside the wonderful word of RxJs.
This challenge is inspired by a real-life example.
### Presentation of the challenge
#### User Story
We need a button for each `Topic`. When we click on it, we delete all objects with this `Topic` in our database _(Fake DB in our case)_. Finally we display **All [topic] have been deleted** is everything was deleted successfully or **Error: deletion of some [topic] failed** if some deletions failed
#### Constraints:
We can only pass one object to our DB for deletion at the time. The DB will respond true if the data was successfully deleted and false otherwise.
### What you need to do
The QA team reports a **bug**. The UI shows **All [topic] have been deleted** all the time, even if some deletions fail.
👉 Spot the bug and correct it.
---
:::note
Start the project by running: `npx nx serve rxjs-pipe-bug`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:11</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3Aanswer"
alt="High Order Operator Bug community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3A'
alt="High Order Operator Bug solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,48 @@ description: Challenge 14 is about race condition in Rxjs
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/rxjs-race-condition/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #14</div>
### Information
The goal of this application is to display a list of topics in a modal when a button is clicked. The application functions correctly. However, your tech lead has asked you to add tests and they are failing.
### Statement
Correct your application to pass the test
### Constraints:
- I can see you coming 🤣 => You CANNOT change the test (Test is working fine) 😳
- You CANNOT change the `fakeGetHttpTopic` method. A delay has been added to fake a slow network.
### Run the test
HEADLESS : `npx nx component-test rxjs-race-condition`
WATCH MODE : `npx nx component-test rxjs-race-condition --watch`
---
:::note
Start the project by running: `npx nx serve rxjs-race-condition`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:14</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3Aanswer"
alt="Race Condition community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3A'
alt="Race Condition solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,50 @@ description: Challenge 17 is about testing the router
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-router-outlet/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #17</div>
### Information
Testing is a crucial step in building scalable, maintainable, and trustworthy applications.
Testing should never be avoided, even in the face of short deadlines or strong pressure from the product team.
Nowadays, there are numerous awesome tools available that make it easy to test your code and provide a great developer experience.
In this series of testing exercises, we will learn and master [Testing Library](https://testing-library.com/docs/) and [Cypress Component Testing](https://docs.cypress.io/guides/component-testing/angular/overview) that simplifies DOM manipulation for testing any Angular component.
### Statement:
We have a functional application that lists available books for borrowing inside a library. If the book you searched is available, you will be directed to the corresponding book(s), otherwise, you will end up on an error page.
The goal is to test this behavior with Testing library and Cypress
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-router-outlet`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-router-outlet` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
---
:::note
Start the project by running: `npx nx serve testing-router-outlet`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:17</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3Aanswer"
alt="Router community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3A'
alt="Router solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,44 @@ description: Challenge 18 is about testing nested components
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-nested/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #18</div>
### Statement:
We have a small application that send a title to a fake backend that you type inside a input.
If the title is correctly typed, you can send the request otherwise you get a nice error and the request is not sent.
You can play with it by running : `npx nx serve testing-nested`.
The goal is to test this behavior with Testing library and Cypress
The file named `child.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `child.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
---
:::note
Start the project by running: `npx nx serve testing-nested`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:18</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3Aanswer"
alt="Nested Components community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3A'
alt="Nested Components solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,43 @@ description: Challenge 19 is about testing inputs and ouputs
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-input-output/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #19</div>
### Statement:
We have a small counter application that increment or decrement a number.
You can play with it by running : `npx nx serve testing-input-output`.
The goal is to test `CounterComponent` with Testing library and Cypress
The file named `counter.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `counter.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
---
:::note
Start the project by running: `npx nx serve testing-input-output`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:19</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3Aanswer"
alt="Input Output community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3A'
alt="Input Output solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,46 @@ description: Challenge 20 is about testing modals
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-modal/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #20</div>
### Statement:
The goal of this challenge is to test dialogs inside your application.
Within this program, you will get an error modal if the user doesn't input a name, while a confirmation modal will appear in all other cases.
In the confirmation modal, if you click the "confirm" button, a message confirming the submission of the form will appear. Otherwise, if the user clicks on "Cancel", an error message will be displayed.
You can play with it by running : `npx nx serve testing-modal`.
The goal is to test this behavior with Testing library and Cypress
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-modal`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-modal` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
I created some `it` blocks but feel free to add more test if you like to.
---
:::note
Start the project by running: `npx nx serve testing-modal`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:20</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3Aanswer"
alt="Modal community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3A'
alt="Modal solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,41 @@ description: Challenge 23 is about testing with component harnesses
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-harness/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #23</div>
### Statement:
The objective of this challenge is to have a better understanding of the CDK test harness API. In this initial challenge, we will only use Angular Material's built-in harnesses.
The goal is to test the functionality of `child.component.ts`. I have prepared a test suite that you need to implement, but feel free to include additional tests as well.
**Note:** You are welcome to use Testing Library if you wish.
Documentation for CDK Component Harness is [here](https://material.angular.io/cdk/test-harnesses/overview#api-for-test-authors)
Documentation for Angular Material component is [here](https://material.angular.io/components/button/overview)
---
:::note
Start the project by running: `npx nx serve testing-harness`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:23</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3Aanswer"
alt="Harness community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3A'
alt="Harness solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,65 @@ description: Challenge 24 is about creating a component harness.
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/create-harness/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #24</div>
### Information
The goal of this challenge is to create a test harness for `slider.component.ts`. The harness file, `slider.harness.ts`, has already been created.
The following API needs to be implemented:
```ts
async clickPlus(): Promise<void> ;
async clickMinus(): Promise<void>;
async getValue(): Promise<number> ;
async getMinValue(): Promise<number>;
async disabled(): Promise<boolean>;
async setValue(value: number): Promise<void>;
```
Additionally, you should create a `HarnessPredicate` with the default predicate and the `minValue` property.
```ts
static with<T extends MySliderHarness>(
this: ComponentHarnessConstructor<T>,
options: SliderHarnessFilters = {}
): HarnessPredicate<T>;
```
Lastly, you will need to create the test suite for `app.component`. Some default tests have already been written, but feel free to add as many tests as you want and create as many harness methods as you need.
> Angular Material documentation can be found [here](https://material.angular.io/cdk/test-harnesses/overview)
Good luck !!! 💪
---
:::note
Start the project by running: `npx nx serve create-harness`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:24</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3Aanswer"
alt="Harness Creation community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3A'
alt="Harness Creation solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,42 @@ description: Challenge 28 is about testing a simple checkbox
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-checkbox/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #28</div>
### Information
This is the perfect example to get started with `Testing Library`.
You will need to only check if the button gets enabled when clicking on the checkbox
You can look into debug function to get full power of `Testing Library` like:
- logRoles(...);
- screen.debug(); // you can pass a element as input
- screen.logTestingPlaygroundURL(); // you can pass a element as input
---
:::note
Start the project by running: `npx nx serve testing-checkbox`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:28</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3Aanswer"
alt="Checkbox community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3A'
alt="Checkbox solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,41 @@ description: Challenge 29 is about testing a real-life application
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/testing-todos-list/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #29</div>
### Statement:
I built this more real life application to create more real life test cases.
In this application, you can search for tickets, you can assign or finish them. You can also create new tickets.
This is a very simple application, but it will let you deal with asynchronous task and mocks
The goal of this challenge is to write all test cases of `ticket.store` , `list.component` and `row.component` with Testing Library.
You can also do it with cypress.
---
:::note
Start the project by running: `npx nx serve testing-todos-list`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:29</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3Aanswer"
alt="Real-life Application community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A285+label%3A'
alt="Real-life Application solution author">
▶︎ Author Answer
</a>
</div>

View File

@@ -4,5 +4,52 @@ description: Challenge 15 is about creating overload functions
--- ---
:::note :::note
WIP: go [here](https://github.com/tomalaforge/angular-challenges/blob/main/apps/overload/README.md) if you want to do this challenge WIP
::: :::
<div class="chip">Challenge #15</div>
### Information
Angular uses TypeScript, and mastering TypeScript can help you avoid runtime errors by catching them at compile time.
In this challenge, we have a function to create a vehicle. However, each vehicle type requires different mandatory properties.
Currently, we are getting an error at runtime if one property is missing and we don't get the return Type, which is not ideal.
One solution would be to create a separate function for each vehicle type, but for this challenge, I want to use the same function and have TypeScript automatically complete the properties depending on the type passed as the first parameter.
To achieve this, we will use overload functions.
### Statement
- Use function overload
---
:::note
Start the project by running: `npx nx serve overload``.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:15</b>.
:::
<div class="article-footer">
<a
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3Aanswer"
alt="Function Overload community solutions">
❖ Community Answers
</a>
<a
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3A'
alt="Function Overload solution author">
▶︎ Author Answer
</a>
<a
href='https://medium.com/ngconf/function-overloading-in-typescript-8236706b2c05'
target="_blank"
rel="noopener noreferrer"
alt="Function Overload blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>