diff --git a/README.md b/README.md
index cd90a9c..04f9e03 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f
## Challenges
-Check [all 52 challenges](https://angular-challenges.vercel.app/)
+Check [all 53 challenges](https://angular-challenges.vercel.app/)
## Contributors ✨
diff --git a/apps/signal/53-big-signal-performance/.eslintrc.json b/apps/signal/53-big-signal-performance/.eslintrc.json
new file mode 100644
index 0000000..d3cd799
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/.eslintrc.json
@@ -0,0 +1,19 @@
+{
+ "extends": ["../../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts"],
+ "extends": [
+ "plugin:@nx/angular",
+ "plugin:@angular-eslint/template/process-inline-templates"
+ ],
+ "rules": {}
+ },
+ {
+ "files": ["*.html"],
+ "extends": ["plugin:@nx/angular-template"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/apps/signal/53-big-signal-performance/README.md b/apps/signal/53-big-signal-performance/README.md
new file mode 100644
index 0000000..2b1b566
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/README.md
@@ -0,0 +1,13 @@
+# Big Signal Performance
+
+> author: thomas-laforge
+
+### Run Application
+
+```bash
+npx nx serve signal-big-signal-performance
+```
+
+### Documentation and Instruction
+
+Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/52-big-signal-performance/).
diff --git a/apps/signal/53-big-signal-performance/project.json b/apps/signal/53-big-signal-performance/project.json
new file mode 100644
index 0000000..b12ba6f
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/project.json
@@ -0,0 +1,72 @@
+{
+ "name": "signal-big-signal-performance",
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "application",
+ "prefix": "app",
+ "sourceRoot": "apps/signal/53-big-signal-performance/src",
+ "tags": [],
+ "targets": {
+ "build": {
+ "executor": "@angular-devkit/build-angular:application",
+ "outputs": ["{options.outputPath}"],
+ "options": {
+ "outputPath": "dist/apps/signal/53-big-signal-performance",
+ "index": "apps/signal/53-big-signal-performance/src/index.html",
+ "browser": "apps/signal/53-big-signal-performance/src/main.ts",
+ "polyfills": ["zone.js"],
+ "tsConfig": "apps/signal/53-big-signal-performance/tsconfig.app.json",
+ "inlineStyleLanguage": "scss",
+ "assets": [
+ "apps/signal/53-big-signal-performance/src/favicon.ico",
+ "apps/signal/53-big-signal-performance/src/assets"
+ ],
+ "styles": ["apps/signal/53-big-signal-performance/src/styles.scss"],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "500kb",
+ "maximumError": "1mb"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "2kb",
+ "maximumError": "4kb"
+ }
+ ],
+ "outputHashing": "all"
+ },
+ "development": {
+ "optimization": false,
+ "extractLicenses": false,
+ "sourceMap": true
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "executor": "@angular-devkit/build-angular:dev-server",
+ "configurations": {
+ "production": {
+ "buildTarget": "signal-big-signal-performance:build:production"
+ },
+ "development": {
+ "buildTarget": "signal-big-signal-performance:build:development"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "extract-i18n": {
+ "executor": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "buildTarget": "signal-big-signal-performance:build"
+ }
+ },
+ "lint": {
+ "executor": "@nx/eslint:lint"
+ }
+ }
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/address.component.ts b/apps/signal/53-big-signal-performance/src/app/address.component.ts
new file mode 100644
index 0000000..ade14dd
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/address.component.ts
@@ -0,0 +1,21 @@
+import { CDFlashingDirective } from '@angular-challenges/shared/directives';
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { UserStore } from './user.service';
+
+@Component({
+ selector: 'address-user',
+ standalone: true,
+ template: `
+
+ Address:
+
Street: {{ userService.user().address.street }}
+
ZipCode: {{ userService.user().address.zipCode }}
+
City: {{ userService.user().address.city }}
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [CDFlashingDirective],
+})
+export class AddressComponent {
+ userService = inject(UserStore);
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/app.component.ts b/apps/signal/53-big-signal-performance/src/app/app.component.ts
new file mode 100644
index 0000000..0d185d2
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/app.component.ts
@@ -0,0 +1,27 @@
+import { Component } from '@angular/core';
+import { AddressComponent } from './address.component';
+import { JobComponent } from './job.component';
+import { NameComponent } from './name.component';
+import { NoteComponent } from './note.component';
+import { UserFormComponent } from './user-form.component';
+
+@Component({
+ standalone: true,
+ selector: 'app-root',
+ template: `
+
+
+
+
+
+ `,
+ styles: [''],
+ imports: [
+ JobComponent,
+ NameComponent,
+ AddressComponent,
+ NoteComponent,
+ UserFormComponent,
+ ],
+})
+export class AppComponent {}
diff --git a/apps/signal/53-big-signal-performance/src/app/app.config.ts b/apps/signal/53-big-signal-performance/src/app/app.config.ts
new file mode 100644
index 0000000..81a6edd
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/app.config.ts
@@ -0,0 +1,5 @@
+import { ApplicationConfig } from '@angular/core';
+
+export const appConfig: ApplicationConfig = {
+ providers: [],
+};
diff --git a/apps/signal/53-big-signal-performance/src/app/job.component.ts b/apps/signal/53-big-signal-performance/src/app/job.component.ts
new file mode 100644
index 0000000..c6710a0
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/job.component.ts
@@ -0,0 +1,20 @@
+import { CDFlashingDirective } from '@angular-challenges/shared/directives';
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { UserStore } from './user.service';
+
+@Component({
+ selector: 'job',
+ standalone: true,
+ template: `
+
+ Job:
+
title: {{ userService.user().title }}
+
salary: {{ userService.user().salary }}
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [CDFlashingDirective],
+})
+export class JobComponent {
+ userService = inject(UserStore);
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/name.component.ts b/apps/signal/53-big-signal-performance/src/app/name.component.ts
new file mode 100644
index 0000000..5317c8e
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/name.component.ts
@@ -0,0 +1,18 @@
+import { CDFlashingDirective } from '@angular-challenges/shared/directives';
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { UserStore } from './user.service';
+
+@Component({
+ selector: 'name',
+ standalone: true,
+ template: `
+
+ Name: {{ userService.user().name }}
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [CDFlashingDirective],
+})
+export class NameComponent {
+ userService = inject(UserStore);
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/note.component.ts b/apps/signal/53-big-signal-performance/src/app/note.component.ts
new file mode 100644
index 0000000..11e8ffe
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/note.component.ts
@@ -0,0 +1,18 @@
+import { CDFlashingDirective } from '@angular-challenges/shared/directives';
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { UserStore } from './user.service';
+
+@Component({
+ selector: 'note',
+ standalone: true,
+ template: `
+
+ Note: {{ userService.user().note }}
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [CDFlashingDirective],
+})
+export class NoteComponent {
+ userService = inject(UserStore);
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/user-form.component.ts b/apps/signal/53-big-signal-performance/src/app/user-form.component.ts
new file mode 100644
index 0000000..7552644
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/user-form.component.ts
@@ -0,0 +1,100 @@
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { UserStore } from './user.service';
+
+@Component({
+ selector: 'user-form',
+ standalone: true,
+ imports: [ReactiveFormsModule],
+ template: `
+
+ `,
+ host: {
+ class: 'block border border-gray-500 p-4 pt-10 m-4',
+ },
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class UserFormComponent {
+ userStore = inject(UserStore);
+
+ form = new FormGroup({
+ name: new FormControl(this.userStore.user().name, { nonNullable: true }),
+ street: new FormControl(this.userStore.user().address.street, {
+ nonNullable: true,
+ }),
+ zipCode: new FormControl(this.userStore.user().address.zipCode, {
+ nonNullable: true,
+ }),
+ city: new FormControl(this.userStore.user().address.city, {
+ nonNullable: true,
+ }),
+ note: new FormControl(this.userStore.user().note, { nonNullable: true }),
+ title: new FormControl(this.userStore.user().title, { nonNullable: true }),
+ salary: new FormControl(this.userStore.user().salary, {
+ nonNullable: true,
+ }),
+ });
+
+ submit() {
+ this.userStore.user.update((u) => ({
+ ...u,
+ name: this.form.getRawValue().name,
+ address: {
+ ...u.address,
+ street: this.form.getRawValue().street,
+ zipCode: this.form.getRawValue().zipCode,
+ city: this.form.getRawValue().city,
+ },
+ note: this.form.getRawValue().note,
+ title: this.form.getRawValue().title,
+ salary: this.form.getRawValue().salary,
+ }));
+ }
+}
diff --git a/apps/signal/53-big-signal-performance/src/app/user.service.ts b/apps/signal/53-big-signal-performance/src/app/user.service.ts
new file mode 100644
index 0000000..4b3b7c5
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/app/user.service.ts
@@ -0,0 +1,16 @@
+import { Injectable, signal } from '@angular/core';
+
+@Injectable({ providedIn: 'root' })
+export class UserStore {
+ user = signal({
+ name: 'Bob',
+ address: {
+ street: '',
+ zipCode: '',
+ city: '',
+ },
+ note: '',
+ title: '',
+ salary: 0,
+ });
+}
diff --git a/apps/signal/53-big-signal-performance/src/assets/.gitkeep b/apps/signal/53-big-signal-performance/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/apps/signal/53-big-signal-performance/src/favicon.ico b/apps/signal/53-big-signal-performance/src/favicon.ico
new file mode 100644
index 0000000..317ebcb
Binary files /dev/null and b/apps/signal/53-big-signal-performance/src/favicon.ico differ
diff --git a/apps/signal/53-big-signal-performance/src/index.html b/apps/signal/53-big-signal-performance/src/index.html
new file mode 100644
index 0000000..3f038cc
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ signal-big-signal-performance
+
+
+
+
+
+
+
+
diff --git a/apps/signal/53-big-signal-performance/src/main.ts b/apps/signal/53-big-signal-performance/src/main.ts
new file mode 100644
index 0000000..f3a7223
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/main.ts
@@ -0,0 +1,7 @@
+import { bootstrapApplication } from '@angular/platform-browser';
+import { AppComponent } from './app/app.component';
+import { appConfig } from './app/app.config';
+
+bootstrapApplication(AppComponent, appConfig).catch((err) =>
+ console.error(err),
+);
diff --git a/apps/signal/53-big-signal-performance/src/styles.scss b/apps/signal/53-big-signal-performance/src/styles.scss
new file mode 100644
index 0000000..77e408a
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/src/styles.scss
@@ -0,0 +1,5 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/* You can add global styles to this file, and also import other style files */
diff --git a/apps/signal/53-big-signal-performance/tailwind.config.js b/apps/signal/53-big-signal-performance/tailwind.config.js
new file mode 100644
index 0000000..38183db
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/tailwind.config.js
@@ -0,0 +1,14 @@
+const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind');
+const { join } = require('path');
+
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
+ ...createGlobPatternsForDependencies(__dirname),
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/apps/signal/53-big-signal-performance/tsconfig.app.json b/apps/signal/53-big-signal-performance/tsconfig.app.json
new file mode 100644
index 0000000..5822042
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/tsconfig.app.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../../dist/out-tsc",
+ "types": []
+ },
+ "files": ["src/main.ts"],
+ "include": ["src/**/*.d.ts"],
+ "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
+}
diff --git a/apps/signal/53-big-signal-performance/tsconfig.editor.json b/apps/signal/53-big-signal-performance/tsconfig.editor.json
new file mode 100644
index 0000000..a8ac182
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/tsconfig.editor.json
@@ -0,0 +1,6 @@
+{
+ "extends": "./tsconfig.json",
+ "include": ["src/**/*.ts"],
+ "compilerOptions": {},
+ "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
+}
diff --git a/apps/signal/53-big-signal-performance/tsconfig.json b/apps/signal/53-big-signal-performance/tsconfig.json
new file mode 100644
index 0000000..3df17b9
--- /dev/null
+++ b/apps/signal/53-big-signal-performance/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "target": "es2022",
+ "useDefineForClassFields": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.editor.json"
+ },
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ],
+ "extends": "../../../tsconfig.base.json",
+ "angularCompilerOptions": {
+ "enableI18nLegacyMessageIdFormat": false,
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
+ }
+}
diff --git a/challenge-number.json b/challenge-number.json
index 024679a..f2a09fd 100644
--- a/challenge-number.json
+++ b/challenge-number.json
@@ -1,6 +1,6 @@
{
- "total": 52,
+ "total": 53,
"🟢": 21,
- "🟠": 121,
+ "🟠": 122,
"🔴": 209
}
diff --git a/docs/src/content/docs/challenges/signal/53-big-signal-performance.md b/docs/src/content/docs/challenges/signal/53-big-signal-performance.md
new file mode 100644
index 0000000..24798ff
--- /dev/null
+++ b/docs/src/content/docs/challenges/signal/53-big-signal-performance.md
@@ -0,0 +1,23 @@
+---
+title: 🟠 Big Signal Performance
+description: Challenge 53 is about performance while using big signal object
+author: thomas-laforge
+contributors:
+ - tomalaforge
+challengeNumber: 53
+command: signal-big-signal-performance
+sidebar:
+ order: 122
+ badge: New
+---
+
+## Information
+
+In this challenge, you can imagine a big application where you store your user state inside a service and you use this service to use your user anywhere in your application.
+The issue is when you update one property of your user, the entire application is updating.
+
+I added the `CDFlashingDirective` to vizualise when one component is rerendering.
+
+## Statement
+
+With Signal, you can now be more fine-grained in what the UI is rerendering. The goal of this challenge is to understand why everything is rerendering and you refactor the application to be more performante.
diff --git a/docs/src/content/docs/es/index.mdx b/docs/src/content/docs/es/index.mdx
index dabaa29..8457c7a 100644
--- a/docs/src/content/docs/es/index.mdx
+++ b/docs/src/content/docs/es/index.mdx
@@ -13,7 +13,7 @@ hero:
icon: right-arrow
variant: primary
- text: Ir al Desafío más reciente
- link: /es/challenges/angular/52-lazy-load-component/
+ link: /es/challenges/signal/53-big-signal-performance/
icon: rocket
- text: Dar una estrella
link: https://github.com/tomalaforge/angular-challenges
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
-
- Este repositorio contiene 52 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript.
+
+ Este repositorio contiene 53 Desafíos relacionados con Angular, Nx, RxJS, Ngrx y Typescript.
Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades.
diff --git a/docs/src/content/docs/fr/index.mdx b/docs/src/content/docs/fr/index.mdx
index 2982de9..fe9eade 100644
--- a/docs/src/content/docs/fr/index.mdx
+++ b/docs/src/content/docs/fr/index.mdx
@@ -13,7 +13,7 @@ hero:
icon: right-arrow
variant: primary
- text: Aller au dernier Challenge
- link: /fr/challenges/angular/52-lazy-load-component/
+ link: /fr/challenges/signal/53-big-signal-performance/
icon: rocket
- text: Donne une étoile
link: https://github.com/tomalaforge/angular-challenges
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
-
- Ce répertoire rassemble 52 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
+
+ Ce répertoire rassemble 53 Défis liés à Angular, Nx, RxJS, Ngrx et Typescript. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
index f44194f..8fb84e8 100644
--- a/docs/src/content/docs/index.mdx
+++ b/docs/src/content/docs/index.mdx
@@ -13,7 +13,7 @@ hero:
icon: right-arrow
variant: primary
- text: Go to the latest Challenge
- link: /challenges/angular/52-lazy-load-component
+ link: /challenges/signal/53-big-signal-performance/
icon: rocket
- text: Give a star
link: https://github.com/tomalaforge/angular-challenges
diff --git a/docs/src/content/docs/pt/index.mdx b/docs/src/content/docs/pt/index.mdx
index 84c7e55..4620405 100644
--- a/docs/src/content/docs/pt/index.mdx
+++ b/docs/src/content/docs/pt/index.mdx
@@ -13,7 +13,7 @@ hero:
icon: right-arrow
variant: primary
- text: Ir para o desafio mais recente
- link: /pt/challenges/angular/52-lazy-load-component/
+ link: /pt/challenges/signal/53-big-signal-performance/
icon: rocket
- text: Dar uma estrela
link: https://github.com/tomalaforge/angular-challenges
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
-
- Este repositório possui 52 Desafios relacionados a Angular, Nx, RxJS,
+
+ Este repositório possui 53 Desafios relacionados a Angular, Nx, RxJS,
Ngrx e Typescript.
Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de
melhorar suas habilidades.
diff --git a/docs/src/content/docs/ru/index.mdx b/docs/src/content/docs/ru/index.mdx
index 0e3e1bf..0802527 100644
--- a/docs/src/content/docs/ru/index.mdx
+++ b/docs/src/content/docs/ru/index.mdx
@@ -13,7 +13,7 @@ hero:
icon: right-arrow
variant: primary
- text: Перейти к последней задаче
- link: /ru/challenges/angular/52-lazy-load-component/
+ link: /ru/challenges/signal/53-big-signal-performance/
icon: rocket
- text: Добавить звезду
link: https://github.com/tomalaforge/angular-challenges
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
-
- Этот репозиторий содержит 51 испытаний, связанных с Angular, Nx, RxJS, Ngrx и Typescript.
+
+ Этот репозиторий содержит 53 испытаний, связанных с Angular, Nx, RxJS, Ngrx и Typescript.
Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас.