Skip to content

Commit 21b0c94

Browse files
committed
feat(injectionToken): create new challenge on injectionToken
1 parent 9aa77fb commit 21b0c94

27 files changed

+385
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f
2424
2525
## Challenges
2626

27-
Check [all 38 challenges](https://angular-challenges.vercel.app/)
27+
Check [all 39 challenges](https://angular-challenges.vercel.app/)
2828

2929
## Contributors ✨
3030

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"extends": ["../../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts"],
7+
"rules": {},
8+
"extends": [
9+
"plugin:@nx/angular",
10+
"plugin:@angular-eslint/template/process-inline-templates"
11+
]
12+
},
13+
{
14+
"files": ["*.html"],
15+
"extends": ["plugin:@nx/angular-template"],
16+
"rules": {}
17+
}
18+
]
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# InjectionToken
2+
3+
> Author: Thomas Laforge
4+
5+
### Run Application
6+
7+
```bash
8+
npx nx serve angular-injection-token
9+
```
10+
11+
### Documentation and Instruction
12+
13+
Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/39-injection-token/).
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'angular-injection-token',
4+
preset: '../../../jest.preset.js',
5+
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
6+
coverageDirectory: '../../../coverage/apps/angular/injection-token',
7+
transform: {
8+
'^.+\\.(ts|mjs|js|html)$': [
9+
'jest-preset-angular',
10+
{
11+
tsconfig: '<rootDir>/tsconfig.spec.json',
12+
stringifyContentPathRegex: '\\.(html|svg)$',
13+
},
14+
],
15+
},
16+
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
17+
snapshotSerializers: [
18+
'jest-preset-angular/build/serializers/no-ng-attributes',
19+
'jest-preset-angular/build/serializers/ng-snapshot',
20+
'jest-preset-angular/build/serializers/html-comment',
21+
],
22+
};
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"name": "angular-injection-token",
3+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
4+
"projectType": "application",
5+
"prefix": "app",
6+
"sourceRoot": "apps/angular/injection-token/src",
7+
"tags": [],
8+
"targets": {
9+
"build": {
10+
"executor": "@angular-devkit/build-angular:browser",
11+
"outputs": ["{options.outputPath}"],
12+
"options": {
13+
"outputPath": "dist/apps/angular/injection-token",
14+
"index": "apps/angular/injection-token/src/index.html",
15+
"main": "apps/angular/injection-token/src/main.ts",
16+
"polyfills": ["zone.js"],
17+
"tsConfig": "apps/angular/injection-token/tsconfig.app.json",
18+
"assets": [
19+
"apps/angular/injection-token/src/favicon.ico",
20+
"apps/angular/injection-token/src/assets"
21+
],
22+
"styles": ["apps/angular/injection-token/src/styles.scss"],
23+
"scripts": []
24+
},
25+
"configurations": {
26+
"production": {
27+
"budgets": [
28+
{
29+
"type": "initial",
30+
"maximumWarning": "500kb",
31+
"maximumError": "1mb"
32+
},
33+
{
34+
"type": "anyComponentStyle",
35+
"maximumWarning": "2kb",
36+
"maximumError": "4kb"
37+
}
38+
],
39+
"outputHashing": "all"
40+
},
41+
"development": {
42+
"buildOptimizer": false,
43+
"optimization": false,
44+
"vendorChunk": true,
45+
"extractLicenses": false,
46+
"sourceMap": true,
47+
"namedChunks": true
48+
}
49+
},
50+
"defaultConfiguration": "production"
51+
},
52+
"serve": {
53+
"executor": "@angular-devkit/build-angular:dev-server",
54+
"configurations": {
55+
"production": {
56+
"browserTarget": "angular-injection-token:build:production"
57+
},
58+
"development": {
59+
"browserTarget": "angular-injection-token:build:development"
60+
}
61+
},
62+
"defaultConfiguration": "development"
63+
},
64+
"extract-i18n": {
65+
"executor": "@angular-devkit/build-angular:extract-i18n",
66+
"options": {
67+
"browserTarget": "angular-injection-token:build"
68+
}
69+
},
70+
"lint": {
71+
"executor": "@nx/linter:eslint",
72+
"outputs": ["{options.outputFile}"],
73+
"options": {
74+
"lintFilePatterns": [
75+
"apps/angular/injection-token/**/*.ts",
76+
"apps/angular/injection-token/**/*.html"
77+
]
78+
}
79+
},
80+
"test": {
81+
"executor": "@nx/jest:jest",
82+
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
83+
"options": {
84+
"jestConfig": "apps/angular/injection-token/jest.config.ts",
85+
"passWithNoTests": true
86+
},
87+
"configurations": {
88+
"ci": {
89+
"ci": true,
90+
"codeCoverage": true
91+
}
92+
}
93+
}
94+
}
95+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Component } from '@angular/core';
2+
import { RouterLink, RouterOutlet } from '@angular/router';
3+
4+
@Component({
5+
standalone: true,
6+
imports: [RouterOutlet, RouterLink],
7+
selector: 'app-root',
8+
template: ` <div class="flex gap-4 mb-5">
9+
<button class="border rounded-md px-4 py-2" routerLink="video">
10+
Video
11+
</button>
12+
<button class="border rounded-md px-4 py-2" routerLink="phone">
13+
Phone
14+
</button>
15+
</div>
16+
<router-outlet />`,
17+
host: {
18+
class: 'p-10 flex flex-col',
19+
},
20+
})
21+
export class AppComponent {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ApplicationConfig } from '@angular/core';
2+
import { provideRouter } from '@angular/router';
3+
4+
export const appConfig: ApplicationConfig = {
5+
providers: [
6+
provideRouter([
7+
{ path: '', pathMatch: 'full', redirectTo: 'video' },
8+
{ path: 'video', loadComponent: () => import('./video.component') },
9+
{ path: 'phone', loadComponent: () => import('./phone.component') },
10+
]),
11+
],
12+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const DEFAULT_TIMER = 1000;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Component } from '@angular/core';
2+
import { TimerContainerComponent } from './timer-container.component';
3+
4+
@Component({
5+
standalone: true,
6+
imports: [TimerContainerComponent],
7+
template: `<div class="flex gap-2">
8+
Phone Call Timer:
9+
<p class="italic">(should be 2000s)</p>
10+
</div>
11+
<timer-container />`,
12+
})
13+
export default class PhoneComponent {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Component } from '@angular/core';
2+
import { DEFAULT_TIMER } from './data';
3+
import { TimerComponent } from './timer.component';
4+
@Component({
5+
selector: 'timer-container',
6+
standalone: true,
7+
imports: [TimerComponent],
8+
template: `
9+
<div class="flex gap-2">
10+
Timer container:
11+
<p class="italic">(timer is {{ timer }}s)</p>
12+
</div>
13+
<timer />
14+
`,
15+
host: {
16+
class: 'border rounded-md flex p-4 gap-10',
17+
},
18+
})
19+
export class TimerContainerComponent {
20+
timer = DEFAULT_TIMER;
21+
}

0 commit comments

Comments
 (0)