├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── package-lock.json ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ └── app.component.ts ├── assets │ ├── .gitkeep │ └── images │ │ └── signal-notif.png ├── favicon.ico ├── index.html ├── main.ts └── styles.scss ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AngularSignals 2 | 3 | ## This project 🎯 explains Angular signals and demonstrates how to create and update signals, use effects, and create computed values 4 | 5 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.0.0-next.2. 6 | 7 | ## Development server 8 | 9 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 10 | 11 | ## Code scaffolding 12 | 13 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 14 | 15 | ## Build 16 | 17 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 18 | 19 | ## Running unit tests 20 | 21 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 22 | 23 | ## Running end-to-end tests 24 | 25 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 26 | 27 | ## Further help 28 | 29 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 30 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-signals": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss" 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "prefix": "app", 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/angular-signals", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": [ 24 | "zone.js" 25 | ], 26 | "tsConfig": "tsconfig.app.json", 27 | "inlineStyleLanguage": "scss", 28 | "assets": [ 29 | "src/favicon.ico", 30 | "src/assets" 31 | ], 32 | "styles": [ 33 | "@angular/material/prebuilt-themes/pink-bluegrey.css", 34 | "src/styles.scss" 35 | ], 36 | "scripts": [] 37 | }, 38 | "configurations": { 39 | "production": { 40 | "budgets": [ 41 | { 42 | "type": "initial", 43 | "maximumWarning": "500kb", 44 | "maximumError": "1mb" 45 | }, 46 | { 47 | "type": "anyComponentStyle", 48 | "maximumWarning": "2kb", 49 | "maximumError": "4kb" 50 | } 51 | ], 52 | "outputHashing": "all" 53 | }, 54 | "development": { 55 | "buildOptimizer": false, 56 | "optimization": false, 57 | "vendorChunk": true, 58 | "extractLicenses": false, 59 | "sourceMap": true, 60 | "namedChunks": true 61 | } 62 | }, 63 | "defaultConfiguration": "production" 64 | }, 65 | "serve": { 66 | "builder": "@angular-devkit/build-angular:dev-server", 67 | "configurations": { 68 | "production": { 69 | "browserTarget": "angular-signals:build:production" 70 | }, 71 | "development": { 72 | "browserTarget": "angular-signals:build:development" 73 | } 74 | }, 75 | "defaultConfiguration": "development" 76 | }, 77 | "extract-i18n": { 78 | "builder": "@angular-devkit/build-angular:extract-i18n", 79 | "options": { 80 | "browserTarget": "angular-signals:build" 81 | } 82 | }, 83 | "test": { 84 | "builder": "@angular-devkit/build-angular:karma", 85 | "options": { 86 | "polyfills": [ 87 | "zone.js", 88 | "zone.js/testing" 89 | ], 90 | "tsConfig": "tsconfig.spec.json", 91 | "inlineStyleLanguage": "scss", 92 | "assets": [ 93 | "src/favicon.ico", 94 | "src/assets" 95 | ], 96 | "styles": [ 97 | "@angular/material/prebuilt-themes/pink-bluegrey.css", 98 | "src/styles.scss" 99 | ], 100 | "scripts": [] 101 | } 102 | } 103 | } 104 | } 105 | }, 106 | "cli": { 107 | "analytics": false 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-signals", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^16.0.0-next.7", 14 | "@angular/cdk": "^16.0.0-next.0", 15 | "@angular/common": "^16.0.0-next.7", 16 | "@angular/compiler": "^16.0.0-next.7", 17 | "@angular/core": "^16.0.0-next.7", 18 | "@angular/forms": "^16.0.0-next.7", 19 | "@angular/material": "^16.0.0-next.0", 20 | "@angular/platform-browser": "^16.0.0-next.7", 21 | "@angular/platform-browser-dynamic": "^16.0.0-next.7", 22 | "@angular/router": "^16.0.0-next.7", 23 | "rxjs": "~7.8.0", 24 | "tslib": "^2.3.0", 25 | "zone.js": "~0.13.0" 26 | }, 27 | "devDependencies": { 28 | "@angular-devkit/build-angular": "^16.0.0-next.7", 29 | "@angular/cli": "~16.0.0-next.7", 30 | "@angular/compiler-cli": "^16.0.0-next.7", 31 | "@types/jasmine": "~4.3.0", 32 | "jasmine-core": "~4.5.0", 33 | "karma": "~6.4.0", 34 | "karma-chrome-launcher": "~3.1.0", 35 | "karma-coverage": "~2.2.0", 36 | "karma-jasmine": "~5.1.0", 37 | "karma-jasmine-html-reporter": "~2.0.0", 38 | "typescript": "~4.9.4" 39 | } 40 | } -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | const routes: Routes = []; 5 | 6 | @NgModule({ 7 | imports: [RouterModule.forRoot(routes)], 8 | exports: [RouterModule] 9 | }) 10 | export class AppRoutingModule { } 11 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | What are Angular Signals 🚦? 5 | {{response1.hidden ? 'expand_more' : 'chevron_right'}} 6 |

7 | 10 |
11 | 12 |
13 |

14 | how do we create a signal ? 15 | {{response2.hidden ? 'expand_more' : 'chevron_right'}} 16 |

17 | 28 |
29 | 30 |
31 |

32 | But what does it mean to notify any dependents?" 😕? 33 | {{response3.hidden ? 'expand_more' : 'chevron_right'}} 34 |

35 | 42 |
43 |
44 |

45 | So, how we can add consumer to Signal ? 46 | {{response4.hidden ? 'expand_more' : 'chevron_right'}} 47 |

48 | 69 | 70 | 71 | 72 |
73 |

I create a signal in the component with movieSig = signal<Movie|null>(null);


74 | 75 |

And I create another signal using computed() 76 | 77 | newMovieSig = computed( () => {{'{'}}
78 | let newMovie ={{'{'}}name : "Titanic",genre : "Romance",releaseYear: 1997, upVote:this.movieSig()?.upVote{{'}'}};
79 | return newMovie;
80 | {{'}'}}
81 |
82 |

83 | 84 |
85 |

And this is the informations of the movie, as you can see, there is no movie because we initialize our Signal with null

86 |
87 |

First Signal

88 |
89 | 90 |
{{movieSig()?.name}}
91 |
92 |
93 | 94 |
{{movieSig()?.genre}}
95 |
96 |
97 | 98 |
{{movieSig()?.releaseYear}}
99 |
100 |
101 | 102 |
{{movieSig()?.upVote}}
103 |
104 |
105 |
106 |

Signal Computed

107 |
108 | 109 |
{{newMovieSig().name}}
110 |
111 |
112 | 113 |
{{newMovieSig().genre}}
114 |
115 |
116 | 117 |
{{newMovieSig().releaseYear}}
118 |
119 |
120 | 121 |
{{newMovieSig().upVote}}
122 |
123 |
124 |
125 | 126 | 127 | 128 |
129 |
130 |

131 | This will execute this code to set new value :
132 | movieSig.set({{'{'}}
133 | name: 'Spider-Man',
134 | genre: 'Action,
135 | Aventure',
136 | releaseYear: 2002{{'{'}})

137 | 138 |

139 | 140 |

141 | This will execute this code to derived a value from the current value :
142 | movieSig.update((movie) => {{'{'}}
143 | if(movie)
144 | movie.upVote+1;
145 | return movie;
146 | })

147 | 148 |

149 | 150 |

151 | This will execute this code to mutate the value :
152 | movieSig.mutate((movie) => {{'{'}}
153 | if (movie) {{'{'}}
154 | movie.upVote = 2000;
155 | {{'}'}}{{'}'}});

156 | 157 |

158 |
159 |
160 |

161 | This will execute this code to create an effect :
162 | runInInjectionContext(this.injector,
163 | () =>(this.effectSig = effect(() => {{'{'}}
164 | alert(`side effect angular signal after movie changes ${{'{'}}JSON.stringify(this.movieSig()
165 | ){{'}'}}`
166 | );{{'}'}})));

167 | 168 | 169 |

170 | 171 | 172 | 173 | 174 |

175 | This will execute this code to destroy the effect :
176 | effectSig?.destroy();
177 | 178 |

179 | 180 |

181 | 182 | 183 |

184 | 185 |
186 |
187 | 188 |
189 |
190 | 191 |
-------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziedzayani/angular-signal-demo/b90f68a3d17428e30005e30a88c0a754698d18f1/src/app/app.component.scss -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule, 10 | AppComponent 11 | ] 12 | }).compileComponents(); 13 | }); 14 | 15 | it('should create the app', () => { 16 | const fixture = TestBed.createComponent(AppComponent); 17 | const app = fixture.componentInstance; 18 | expect(app).toBeTruthy(); 19 | }); 20 | 21 | it(`should have as title 'angular-signals'`, () => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | const app = fixture.componentInstance; 24 | expect(app.title).toEqual('angular-signals'); 25 | }); 26 | 27 | it('should render title', () => { 28 | const fixture = TestBed.createComponent(AppComponent); 29 | fixture.detectChanges(); 30 | const compiled = fixture.nativeElement as HTMLElement; 31 | expect(compiled.querySelector('.content span')?.textContent).toContain('angular-signals app is running!'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | signal, 4 | computed, 5 | Signal, 6 | EffectRef, 7 | effect, 8 | Injector, 9 | Inject, 10 | inject, 11 | EnvironmentInjector, 12 | runInInjectionContext, 13 | } from '@angular/core'; 14 | import { RouterOutlet } from '@angular/router'; 15 | import { MatIconModule } from '@angular/material/icon'; 16 | import { 17 | trigger, 18 | state, 19 | style, 20 | transition, 21 | animate, 22 | } from '@angular/animations'; 23 | import { MatButtonModule } from '@angular/material/button'; 24 | 25 | export interface Movie { 26 | name: string; 27 | genre: string; 28 | releaseYear: number; 29 | upVote: number; 30 | } 31 | 32 | @Component({ 33 | selector: 'app-root', 34 | templateUrl: './app.component.html', 35 | styleUrls: ['./app.component.scss'], 36 | standalone: true, 37 | imports: [MatIconModule, RouterOutlet, MatButtonModule], 38 | animations: [ 39 | trigger('slideInOut', [ 40 | state( 41 | 'in', 42 | style({ 43 | 'max-height': '1000px', 44 | opacity: '1', 45 | visibility: 'visible', 46 | }) 47 | ), 48 | state( 49 | 'out', 50 | style({ 51 | 'max-height': '0px', 52 | opacity: '0', 53 | visibility: 'hidden', 54 | }) 55 | ), 56 | transition('in => out', [animate('400ms ease-in-out')]), 57 | transition('out => in', [animate('400ms ease-in-out')]), 58 | ]), 59 | ], 60 | }) 61 | export class AppComponent { 62 | movieSig = signal(null); 63 | injector = inject(EnvironmentInjector); 64 | newMovieSig = computed(() => { 65 | let newMovie = { 66 | name: 'Titanic', 67 | genre: 'Romance', 68 | releaseYear: 1997, 69 | upVote: this.movieSig()?.upVote, 70 | }; 71 | return newMovie; 72 | }); 73 | effectSig!: EffectRef; 74 | title = 'angular-signals'; 75 | 76 | setMovie() { 77 | this.movieSig.set({ 78 | name: 'Spider-Man', 79 | genre: 'Action, Aventure', 80 | releaseYear: 2002, 81 | upVote: 8, 82 | }); 83 | } 84 | 85 | updateMovie() { 86 | this.movieSig.update((movie) => { 87 | if (movie) movie.upVote = movie.upVote + 1; 88 | return movie; 89 | }); 90 | } 91 | 92 | mutateMovie() { 93 | this.movieSig.mutate((movie) => { 94 | if (movie) { 95 | movie.upVote = 2000; 96 | } 97 | }); 98 | } 99 | 100 | createEffect() { 101 | runInInjectionContext(this.injector, 102 | () => 103 | (this.effectSig = effect(() => { 104 | alert( 105 | `side effect angular signal after movie changes ${JSON.stringify( 106 | this.movieSig() 107 | )}` 108 | ); 109 | })) 110 | ); 111 | } 112 | 113 | destroyEffect() { 114 | this.effectSig?.destroy(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziedzayani/angular-signal-demo/b90f68a3d17428e30005e30a88c0a754698d18f1/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/images/signal-notif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziedzayani/angular-signal-demo/b90f68a3d17428e30005e30a88c0a754698d18f1/src/assets/images/signal-notif.png -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR?�~� pHYs  ��~�fIDATH��WKLQ���̔�uG�� e�n�. 6qcb�l?���D`�F#� Ku�F 1Qc� 4 | ��!���� ��C�P�|B?$���ܱ3����I&}��}�̽s�[*�ɀU�A��K��yx�gY�Ajq��3L Š���˫�OD�4��3Ϗ:X�3��o�P J�ğo#IH�a����,{>1/�2$�R AR]�)w��?�sZw^��q�Y�m_��e���r[8�^� 5 | �&p��-���A}c��- ������!����2_) E�)㊪j���v�m��ZOi� g�nW�{�n.|�e2�a&�0aŸ����be�̀��C�fˤE%-{�ֺ��׮C��N��jXi�~c�C,t��T�����r�{� �L)s��V��6%�(�#ᤙ!�]��H�ҐH$R���^R�A�61(?Y舚�>���(Z����Qm�L2�K�ZIc�� 6 | ���̧�C��2!⅄�(����"�Go��>�q��=��$%�z`ѯ��T�&����PHh�Z!=���z��O��������,*VVV�1�f*CJ�]EE��K�k��d�#5���`2yT!�}7���߈~�,���zs�����y�T��V������D��C2�G��@%̑72Y�޾{oJ�"@��^h�~ ��fĬ�!a�D��6���Ha|�3��� [>�����]7U2п���]�ė 7 | ��PU� �.Wejq�in�g��+p<ߺQH����總j[������.��� Q���p _�K�� 1(��+��bB8�\ra 8 | �́�v.l���(���ǽ�w���L��w�8�C��IEND�B`� -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularSignals 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | 4 | import { importProvidersFrom } from '@angular/core'; 5 | import { AppComponent } from './app/app.component'; 6 | import { provideAnimations } from '@angular/platform-browser/animations'; 7 | import { AppRoutingModule } from './app/app-routing.module'; 8 | import { BrowserModule, bootstrapApplication } from '@angular/platform-browser'; 9 | 10 | 11 | bootstrapApplication(AppComponent, { 12 | providers: [ 13 | importProvidersFrom(BrowserModule, AppRoutingModule), 14 | provideAnimations() 15 | ] 16 | }) 17 | .catch(err => console.error(err)); 18 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html { height: 100%; } 4 | 5 | body { 6 | background: linear-gradient(to bottom right, #0f172a, #1a2f49); 7 | color: #ffffff; 8 | display: flex; 9 | flex-direction: column; 10 | align-items: center; 11 | justify-content: center; 12 | height: 100vh; 13 | margin: 0; 14 | overflow-x: hidden; 15 | background-attachment: fixed; 16 | } 17 | 18 | code { 19 | font-family: 'Consolas', 'Courier New', monospace; 20 | background-color: #334155; 21 | color: #d4d4d4; 22 | padding: 0.2rem 0.4rem; 23 | border-radius: 3px; 24 | display: inline-block; 25 | } 26 | .container { 27 | position: absolute; 28 | top: 50px; 29 | left: 50%; 30 | transform: translateX(-50%); 31 | width: 80%; 32 | } 33 | 34 | .container { 35 | max-width: 70%; 36 | margin: auto; 37 | } 38 | 39 | .bloc { 40 | display: flex; 41 | align-items: center; 42 | justify-content: space-between; 43 | padding: 10px; 44 | background-color: #334155; 45 | border-radius: 5px; 46 | margin-bottom: 10px; 47 | cursor: pointer; 48 | } 49 | 50 | .bloc mat-icon { 51 | font-size: 1.2rem; 52 | transition: transform 0.6s ease-in-out; 53 | } 54 | 55 | .bloc p { 56 | margin: 0; 57 | padding: 10px; 58 | background-color: #334155; 59 | border-radius: 5px; 60 | overflow: hidden; 61 | } 62 | 63 | .image-container { 64 | margin-bottom: 20px; 65 | text-align: center; 66 | overflow: auto; 67 | padding-bottom: 20px; 68 | } 69 | 70 | .bloc p.animate-show { 71 | animation: show 0.6s ease-in-out forwards; 72 | } 73 | 74 | .bloc p.animate-hide { 75 | animation: hide 0.6s ease-in-out forwards; 76 | } 77 | 78 | .response { 79 | margin: 2rem; 80 | margin-bottom: 20px; 81 | } 82 | 83 | .reactive-space { 84 | font-size: 0.8rem; 85 | padding: 2rem; 86 | max-width: 100%; 87 | height: 1000px; 88 | background-color: #07172e; 89 | 90 | } 91 | .info-container { 92 | display: flex; 93 | flex-wrap: wrap; 94 | justify-content: flex-start; 95 | } 96 | 97 | .row { 98 | display: flex; 99 | align-items: center; 100 | margin-bottom: 10px; 101 | flex-basis: 50%; 102 | } 103 | 104 | .row label { 105 | width: 120px; 106 | margin-right: 10px; 107 | } 108 | 109 | .column-container { 110 | display: flex; 111 | } 112 | 113 | .column-container .column { 114 | flex-basis: 50%; 115 | height: 30rem; 116 | padding: 0 10px; 117 | } 118 | 119 | .column-container .column p { 120 | height: 10rem; 121 | } 122 | 123 | @media only screen and (max-width: 800px) { 124 | .row { 125 | display: block; 126 | } 127 | .row > div { 128 | display: inline-block; 129 | margin-bottom: 10px; 130 | } 131 | } 132 | 133 | @media only screen and (max-width: 1100px) { 134 | div { 135 | display: flex; 136 | flex-direction: column; 137 | } 138 | 139 | p { 140 | margin-bottom: 1rem; 141 | } 142 | } 143 | 144 | 145 | 146 | 147 | @keyframes show { 148 | from { 149 | height: 0; 150 | opacity: 0; 151 | } 152 | to { 153 | height: auto; 154 | opacity: 1; 155 | } 156 | } 157 | 158 | @keyframes hide { 159 | from { 160 | height: auto; 161 | opacity: 1; 162 | } 163 | to { 164 | height: 0; 165 | opacity: 0; 166 | } 167 | } -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | --------------------------------------------------------------------------------